Squashed commit of the following:

commit b87b6b2a96de870f1782b00cfe3f393cc79b7d3b
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Mon Dec 18 14:05:11 2017 +0000

    Even more tests for this micropub refactor

commit 2d967f33c3abeea8fc89f91e1764e970681dc58f
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Sat Dec 16 22:19:53 2017 +0000

    Fill out token endpoint tests

commit 440dcbe3e53f058060c918429bea75911ddafdc1
Merge: 02a25b0 f60164f
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Dec 15 14:32:50 2017 +0000

    Merge pull request #77 from jonnybarnes/analysis-8KABW6

    Apply fixes from StyleCI

commit f60164fe81dbcc1d2343704145d26c6d6412579a
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Dec 15 14:27:40 2017 +0000

    Apply fixes from StyleCI

commit 02a25b083a0305f73d715feb3f9d34f9de8f67d4
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Dec 15 14:17:43 2017 +0000

    phpcs fix

commit 144998de0866bf11f235847d7edc076235294545
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Dec 15 14:16:59 2017 +0000

    Don’t pass the request object to service files, pass request()->all()

commit dd5e52010c51a359665efa349ff8c13d4d6dbf57
Merge: 97b270a 23b145e
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Sun Dec 10 20:01:03 2017 +0000

    Merge pull request #76 from jonnybarnes/analysis-86AVg6

    Apply fixes from StyleCI

commit 23b145e7bf67a358b3cb894ea0793984b65ecab5
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Sun Dec 10 19:50:53 2017 +0000

    Apply fixes from StyleCI

commit 97b270a89abe92e167e0d363029ae0b86608bbc9
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Sun Dec 10 19:43:38 2017 +0000

    Improve test coverage of the refactor

commit 244102264559e4fb0b0614d1738c0283703a71dc
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Dec 8 13:31:13 2017 +0000

    Refactor the note creation code

commit 22b4786cbd7ae508b51a47f0c8cf9a15535edbb1
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Thu Dec 7 17:39:41 2017 +0000

    Remove ununsed importsed classes in the controller
This commit is contained in:
Jonny Barnes 2017-12-18 15:51:02 +00:00
parent d409098efb
commit 43beae2f82
15 changed files with 875 additions and 286 deletions

View file

@ -2,14 +2,21 @@
namespace Tests\Feature;
use App\Media;
use App\Place;
use Carbon\Carbon;
use Tests\TestCase;
use Tests\TestToken;
use Lcobucci\JWT\Builder;
use App\Jobs\ProcessMedia;
use App\Jobs\SendWebMentions;
use Illuminate\Http\UploadedFile;
use App\Jobs\SyndicateNoteToTwitter;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use App\Jobs\SyndicateNoteToFacebook;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Storage;
use Phaza\LaravelPostgis\Geometries\Point;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class MicropubControllerTest extends TestCase
@ -124,7 +131,9 @@ class MicropubControllerTest extends TestCase
'/api/post',
[
'h' => 'entry',
'content' => $note
'content' => $note,
'published' => Carbon::now()->toW3CString(),
'location' => 'geo:1.23,4.56',
],
[],
[],
@ -134,6 +143,60 @@ class MicropubControllerTest extends TestCase
$this->assertDatabaseHas('notes', ['note' => $note]);
}
/**
* Test a valid micropub requests creates a new note and syndicates to Twitter.
*
* @return void
*/
public function test_micropub_post_request_creates_new_note_sends_to_twitter()
{
Queue::fake();
$faker = \Faker\Factory::create();
$note = $faker->text;
$response = $this->call(
'POST',
'/api/post',
[
'h' => 'entry',
'content' => $note,
'mp-syndicate-to' => 'https://twitter.com/jonnybarnes'
],
[],
[],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response->assertJson(['response' => 'created']);
$this->assertDatabaseHas('notes', ['note' => $note]);
Queue::assertPushed(SyndicateNoteToTwitter::class);
}
/**
* Test a valid micropub requests creates a new note and syndicates to Facebook.
*
* @return void
*/
public function test_micropub_post_request_creates_new_note_sends_to_facebook()
{
Queue::fake();
$faker = \Faker\Factory::create();
$note = $faker->text;
$response = $this->call(
'POST',
'/api/post',
[
'h' => 'entry',
'content' => $note,
'mp-syndicate-to' => 'https://facebook.com/jonnybarnes'
],
[],
[],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response->assertJson(['response' => 'created']);
$this->assertDatabaseHas('notes', ['note' => $note]);
Queue::assertPushed(SyndicateNoteToFacebook::class);
}
/**
* Test a valid micropub requests creates a new place.
*
@ -182,12 +245,135 @@ class MicropubControllerTest extends TestCase
$this->assertDatabaseHas('places', ['slug' => 'the-barton-arms']);
}
public function test_micropub_post_request_with_invalid_token_returns_expected_error_response()
{
$response = $this->call(
'POST',
'/api/post',
[
'h' => 'entry',
'content' => 'A random note',
],
[],
[],
['HTTP_Authorization' => 'Bearer ' . $this->getInvalidToken()]
);
$response->assertStatus(400);
$response->assertJson(['error' => 'invalid_token']);
}
public function test_micropub_post_request_with_scopeless_token_returns_expected_error_response()
{
$response = $this->call(
'POST',
'/api/post',
[
'h' => 'entry',
'content' => 'A random note',
],
[],
[],
['HTTP_Authorization' => 'Bearer ' . $this->getTokenWithNoScope()]
);
$response->assertStatus(400);
$response->assertJson(['error_description' => 'The provided token has no scopes']);
}
public function test_micropub_post_request_for_place_without_create_scope_errors()
{
$response = $this->call(
'POST',
'/api/post',
[
'h' => 'card',
'name' => 'The Barton Arms',
'geo' => 'geo:53.4974,-2.3768'
],
[],
[],
['HTTP_Authorization' => 'Bearer ' . $this->getTokenWithIncorrectScope()]
);
$response->assertStatus(401);
$response->assertJson(['error' => 'insufficient_scope']);
}
/**
* Test a valid micropub requests using JSON syntax creates a new note.
*
* @return void
*/
public function test_micropub_post_request_with_json_syntax_creates_new_note()
{
Queue::fake();
Media::create([
'path' => 'test-photo.jpg',
'type' => 'image',
]);
$faker = \Faker\Factory::create();
$note = $faker->text;
$response = $this->json(
'POST',
'/api/post',
[
'type' => ['h-entry'],
'properties' => [
'content' => [$note],
'in-reply-to' => ['https://aaronpk.localhost'],
'mp-syndicate-to' => [
'https://twitter.com/jonnybarnes',
'https://facebook.com/jonnybarnes',
],
'photo' => [config('filesystems.disks.s3.url') . '/test-photo.jpg'],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response
->assertStatus(201)
->assertJson(['response' => 'created']);
Queue::assertPushed(SendWebMentions::class);
Queue::assertPushed(SyndicateNoteToTwitter::class);
Queue::assertPushed(SyndicateNoteToFacebook::class);
}
/**
* Test a valid micropub requests using JSON syntax creates a new note with
* existing self-created place.
*
* @return void
*/
public function test_micropub_post_request_with_json_syntax_creates_new_note_with_existing_place_in_location()
{
$place = new Place();
$place->name = 'Test Place';
$place->location = new Point((float) 1.23, (float) 4.56);
$place->save();
$faker = \Faker\Factory::create();
$note = $faker->text;
$response = $this->json(
'POST',
'/api/post',
[
'type' => ['h-entry'],
'properties' => [
'content' => [$note],
'location' => [$place->longurl],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response
->assertStatus(201)
->assertJson(['response' => 'created']);
}
/**
* Test a valid micropub requests using JSON syntax creates a new note with
* a new place defined in the location block.
*
* @return void
*/
public function test_micropub_post_request_with_json_syntax_creates_new_note_with_new_place_in_location()
{
$faker = \Faker\Factory::create();
$note = $faker->text;
@ -198,6 +384,14 @@ class MicropubControllerTest extends TestCase
'type' => ['h-entry'],
'properties' => [
'content' => [$note],
'location' => [[
'type' => ['h-card'],
'properties' => [
'name' => ['Awesome Venue'],
'latitude' => ['1.23'],
'longitude' => ['4.56'],
],
]],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
@ -205,6 +399,44 @@ class MicropubControllerTest extends TestCase
$response
->assertStatus(201)
->assertJson(['response' => 'created']);
$this->assertDatabaseHas('places', [
'name' => 'Awesome Venue',
]);
}
/**
* Test a valid micropub requests using JSON syntax creates a new note without
* a new place defined in the location block if there is missing data.
*
* @return void
*/
public function test_micropub_post_request_with_json_syntax_creates_new_note_without_new_place_in_location()
{
$faker = \Faker\Factory::create();
$note = $faker->text;
$response = $this->json(
'POST',
'/api/post',
[
'type' => ['h-entry'],
'properties' => [
'content' => [$note],
'location' => [[
'type' => ['h-card'],
'properties' => [
'name' => ['Awesome Venue'],
],
]],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response
->assertStatus(201)
->assertJson(['response' => 'created']);
$this->assertDatabaseMissing('places', [
'name' => 'Awesome Venue',
]);
}
/**
@ -236,12 +468,12 @@ class MicropubControllerTest extends TestCase
}
/**
* Test a micropub requests using JSON syntax without a valis token returns
* Test a micropub requests using JSON syntax without a valid token returns
* an error. Also check the message.
*
* @return void
*/
public function test_micropub_post_request_with_json_syntax_with_invalid_token_returns_error()
public function test_micropub_post_request_with_json_syntax_with_insufficient_token_returns_error()
{
$faker = \Faker\Factory::create();
$note = $faker->text;
@ -254,7 +486,7 @@ class MicropubControllerTest extends TestCase
'content' => [$note],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getInvalidToken()]
['HTTP_Authorization' => 'Bearer ' . $this->getTokenWithIncorrectScope()]
);
$response
->assertJson([
@ -264,6 +496,27 @@ class MicropubControllerTest extends TestCase
->assertStatus(401);
}
public function test_micropub_post_request_with_json_syntax_for_unsupported_type_returns_error()
{
$response = $this->json(
'POST',
'/api/post',
[
'type' => ['h-unsopported'], // a request type I dont support
'properties' => [
'content' => ['Some content'],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response
->assertJson([
'response' => 'error',
'error_description' => 'unsupported_request_type'
])
->assertStatus(500);
}
public function test_micropub_post_request_with_json_syntax_creates_new_place()
{
$faker = \Faker\Factory::create();
@ -332,7 +585,10 @@ class MicropubControllerTest extends TestCase
'action' => 'update',
'url' => config('app.url') . '/notes/A',
'add' => [
'syndication' => ['https://www.swarmapp.com/checkin/123'],
'syndication' => [
'https://www.swarmapp.com/checkin/123',
'https://www.facebook.com/checkin/123',
],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
@ -341,7 +597,132 @@ class MicropubControllerTest extends TestCase
->assertJson(['response' => 'updated'])
->assertStatus(200);
$this->assertDatabaseHas('notes', [
'swarm_url' => 'https://www.swarmapp.com/checkin/123'
'swarm_url' => 'https://www.swarmapp.com/checkin/123',
'facebook_url' => 'https://www.facebook.com/checkin/123',
]);
}
public function test_micropub_post_request_with_json_syntax_update_add_image_to_post()
{
$response = $this->json(
'POST',
'/api/post',
[
'action' => 'update',
'url' => config('app.url') . '/notes/A',
'add' => [
'photo' => ['https://example.org/photo.jpg'],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response
->assertJson(['response' => 'updated'])
->assertStatus(200);
$this->assertDatabaseHas('media_endpoint', [
'path' => 'https://example.org/photo.jpg',
]);
}
public function test_micropub_post_request_with_json_syntax_update_add_post_errors_for_non_note()
{
$response = $this->json(
'POST',
'/api/post',
[
'action' => 'update',
'url' => config('app.url') . '/blog/A',
'add' => [
'syndication' => ['https://www.swarmapp.com/checkin/123'],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response
->assertJson(['error' => 'invalid'])
->assertStatus(500);
}
public function test_micropub_post_request_with_json_syntax_update_add_post_errors_for_note_not_found()
{
$response = $this->json(
'POST',
'/api/post',
[
'action' => 'update',
'url' => config('app.url') . '/notes/ZZZZ',
'add' => [
'syndication' => ['https://www.swarmapp.com/checkin/123'],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response
->assertJson(['error' => 'invalid_request'])
->assertStatus(404);
}
public function test_micropub_post_request_with_json_syntax_update_add_post_errors_for_unsupported_request()
{
$response = $this->json(
'POST',
'/api/post',
[
'action' => 'update',
'url' => config('app.url') . '/notes/A',
'morph' => [ // or any other unsupported update type
'syndication' => ['https://www.swarmapp.com/checkin/123'],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response
->assertJson(['response' => 'error'])
->assertStatus(500);
}
public function test_micropub_post_request_with_json_syntax_update_errors_for_insufficient_scope()
{
$response = $this->json(
'POST',
'/api/post',
[
'action' => 'update',
'url' => config('app.url') . '/notes/B',
'add' => [
'syndication' => ['https://www.swarmapp.com/checkin/123'],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getTokenWithIncorrectScope()]
);
$response
->assertStatus(401)
->assertJson(['error' => 'insufficient_scope']);
}
public function test_micropub_post_request_with_json_syntax_update_replace_post_syndication()
{
$response = $this->json(
'POST',
'/api/post',
[
'action' => 'update',
'url' => config('app.url') . '/notes/L',
'replace' => [
'syndication' => [
'https://www.swarmapp.com/checkin/the-id',
'https://www.facebook.com/post/the-id',
],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response
->assertJson(['response' => 'updated'])
->assertStatus(200);
$this->assertDatabaseHas('notes', [
'swarm_url' => 'https://www.swarmapp.com/checkin/the-id',
'facebook_url' => 'https://www.facebook.com/post/the-id',
]);
}
@ -359,6 +740,20 @@ class MicropubControllerTest extends TestCase
$response->assertJsonFragment(['error_description' => 'The provided token did not pass validation']);
}
public function test_media_endpoint_request_with_token_with_no_scope_returns_400_response()
{
$response = $this->call(
'POST',
'/api/media',
[],
[],
[],
['HTTP_Authorization' => 'Bearer ' . $this->getTokenWithNoScope()]
);
$response->assertStatus(400);
$response->assertJsonFragment(['error_description' => 'The provided token has no scopes']);
}
public function test_media_endpoint_request_with_insufficient_token_scopes_returns_401_response()
{
$response = $this->call(
@ -367,7 +762,7 @@ class MicropubControllerTest extends TestCase
[],
[],
[],
['HTTP_Authorization' => 'Bearer ' . $this->getInvalidToken()]
['HTTP_Authorization' => 'Bearer ' . $this->getTokenWithIncorrectScope()]
);
$response->assertStatus(401);
$response->assertJsonFragment(['error_description' => 'The tokens scope does not have the necessary requirements.']);
@ -394,4 +789,91 @@ class MicropubControllerTest extends TestCase
Queue::assertPushed(ProcessMedia::class);
Storage::disk('local')->assertExists($filename);
}
public function test_media_endpoint_upload_an_audio_file()
{
Queue::fake();
Storage::fake('local');
$file = __DIR__ . '/../audio.mp3';
$response = $this->call(
'POST',
'/api/media',
[],
[],
[
'file' => new UploadedFile($file, 'audio.mp3', 'audio/mpeg', filesize($file), null, true),
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$path = parse_url($response->getData()->location, PHP_URL_PATH);
$filename = substr($path, 7);
Queue::assertPushed(ProcessMedia::class);
Storage::disk('local')->assertExists($filename);
}
public function test_media_endpoint_upload_a_video_file()
{
Queue::fake();
Storage::fake('local');
$file = __DIR__ . '/../video.ogv';
$response = $this->call(
'POST',
'/api/media',
[],
[],
[
'file' => new UploadedFile($file, 'video.ogv', 'video/ogg', filesize($file), null, true),
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$path = parse_url($response->getData()->location, PHP_URL_PATH);
$filename = substr($path, 7);
Queue::assertPushed(ProcessMedia::class);
Storage::disk('local')->assertExists($filename);
}
public function test_media_endpoint_upload_a_document_file()
{
Queue::fake();
Storage::fake('local');
$response = $this->call(
'POST',
'/api/media',
[],
[],
[
'file' => UploadedFile::fake()->create('document.pdf', 100),
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$path = parse_url($response->getData()->location, PHP_URL_PATH);
$filename = substr($path, 7);
Queue::assertPushed(ProcessMedia::class);
Storage::disk('local')->assertExists($filename);
}
public function test_media_endpoint_upload_an_invalid_file_return_error()
{
Queue::fake();
Storage::fake('local');
$response = $this->call(
'POST',
'/api/media',
[],
[],
[
'file' => new UploadedFile(__DIR__ . '/../aaron.png', 'aaron.png', 'image/png', UPLOAD_ERR_INI_SIZE, true),
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response->assertStatus(400);
$response->assertJson(['error_description' => 'The uploaded file failed validation']);
}
}