mirror of https://github.com/pixelfed/pixelfed
test: add notification, search, compose, report, and collection tests (332 total)
Api/NotificationTest: notification isolation, correct user filtering Api/SearchTest: v2 search auth, structure, account lookup Api/CollectionTest: self/user collections, auth requirement Compose/ComposeTest: page access, settings, media validation, autocomplete Account/ReportTest: report creation, type validation, auth requirementpull/6858/head
parent
e1f883a41b
commit
0f3820e7bf
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
use App\Report;
|
||||
use App\Status;
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
|
||||
|
||||
uses(LazilyRefreshDatabase::class);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Report Tests
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
describe('report submission', function () {
|
||||
it('creates a report for a status', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
$other = User::factory()->create();
|
||||
$other->refresh();
|
||||
$status = Status::factory()->create([
|
||||
'profile_id' => $other->profile_id,
|
||||
'type' => 'photo',
|
||||
]);
|
||||
|
||||
$this->actingAs($user)
|
||||
->postJson('/i/report', [
|
||||
'report' => 'spam',
|
||||
'type' => 'post',
|
||||
'id' => $status->id,
|
||||
'msg' => 'This is spam content',
|
||||
])
|
||||
->assertOk();
|
||||
|
||||
expect(Report::where('profile_id', $user->profile_id)->exists())->toBeTrue();
|
||||
});
|
||||
|
||||
it('rejects report with invalid type', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
|
||||
$this->actingAs($user)
|
||||
->postJson('/i/report', [
|
||||
'report' => 'invalid_type',
|
||||
'type' => 'post',
|
||||
'id' => 1,
|
||||
])
|
||||
->assertStatus(400);
|
||||
});
|
||||
|
||||
it('validates required fields', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
|
||||
$this->actingAs($user)
|
||||
->postJson('/i/report', [])
|
||||
->assertUnprocessable();
|
||||
});
|
||||
|
||||
it('requires authentication', function () {
|
||||
$this->postJson('/i/report', [
|
||||
'report' => 'spam',
|
||||
'type' => 'post',
|
||||
'id' => 1,
|
||||
])->assertUnauthorized();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
|
||||
use Laravel\Passport\Passport;
|
||||
|
||||
uses(LazilyRefreshDatabase::class);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Collection Tests
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
describe('collections', function () {
|
||||
it('lists self collections', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
Passport::actingAs($user, ['read']);
|
||||
|
||||
$this->getJson('/api/pixelfed/v1/collections/self')
|
||||
->assertOk()
|
||||
->assertJsonIsArray();
|
||||
});
|
||||
|
||||
it('lists user collections by account id', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
Passport::actingAs($user, ['read']);
|
||||
|
||||
$this->getJson("/api/pixelfed/v1/collections/accounts/{$user->profile_id}")
|
||||
->assertOk()
|
||||
->assertJsonIsArray();
|
||||
});
|
||||
|
||||
it('returns 404 for non-existent collection', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
Passport::actingAs($user, ['read']);
|
||||
|
||||
$this->getJson('/api/pixelfed/v1/collections/view/999999')
|
||||
->assertNotFound();
|
||||
});
|
||||
|
||||
it('requires authentication for self collections', function () {
|
||||
$this->getJson('/api/pixelfed/v1/collections/self')
|
||||
->assertUnauthorized();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
use App\Like;
|
||||
use App\Notification;
|
||||
use App\Status;
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
|
||||
use Laravel\Passport\Passport;
|
||||
|
||||
uses(LazilyRefreshDatabase::class);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Notification API Tests
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
describe('GET /api/v1/notifications', function () {
|
||||
it('returns empty array for user with no notifications', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
Passport::actingAs($user, ['read']);
|
||||
|
||||
$this->getJson('/api/v1/notifications')
|
||||
->assertOk()
|
||||
->assertJson([]);
|
||||
});
|
||||
|
||||
it('returns notifications for authenticated user', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
$other = User::factory()->create();
|
||||
$other->refresh();
|
||||
$status = Status::factory()->create([
|
||||
'profile_id' => $user->profile_id,
|
||||
'type' => 'photo',
|
||||
]);
|
||||
|
||||
Notification::create([
|
||||
'profile_id' => $user->profile_id,
|
||||
'actor_id' => $other->profile_id,
|
||||
'action' => 'like',
|
||||
'item_id' => $status->id,
|
||||
'item_type' => Status::class,
|
||||
]);
|
||||
|
||||
Passport::actingAs($user, ['read']);
|
||||
|
||||
$this->getJson('/api/v1/notifications')
|
||||
->assertOk()
|
||||
->assertJsonIsArray();
|
||||
});
|
||||
|
||||
it('does not return other users notifications', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
$other = User::factory()->create();
|
||||
$other->refresh();
|
||||
|
||||
Notification::create([
|
||||
'profile_id' => $other->profile_id,
|
||||
'actor_id' => $user->profile_id,
|
||||
'action' => 'follow',
|
||||
'item_id' => $other->profile_id,
|
||||
'item_type' => \App\Profile::class,
|
||||
]);
|
||||
|
||||
Passport::actingAs($user, ['read']);
|
||||
|
||||
$this->getJson('/api/v1/notifications')
|
||||
->assertOk()
|
||||
->assertJson([]);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
|
||||
use Laravel\Passport\Passport;
|
||||
|
||||
uses(LazilyRefreshDatabase::class);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Search API Tests
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
describe('GET /api/v2/search', function () {
|
||||
it('requires authentication', function () {
|
||||
$this->getJson('/api/v2/search?q=test')
|
||||
->assertUnauthorized();
|
||||
});
|
||||
|
||||
it('returns results structure for a query', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
Passport::actingAs($user, ['read']);
|
||||
|
||||
$this->getJson('/api/v2/search?q=test')
|
||||
->assertOk()
|
||||
->assertJsonStructure(['accounts', 'statuses', 'hashtags']);
|
||||
});
|
||||
|
||||
it('rejects empty query', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
Passport::actingAs($user, ['read']);
|
||||
|
||||
$this->getJson('/api/v2/search?q=')
|
||||
->assertStatus(422);
|
||||
});
|
||||
|
||||
it('finds local accounts by username', function () {
|
||||
$target = User::factory()->create(['username' => 'searchable']);
|
||||
$target->refresh();
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
Passport::actingAs($user, ['read']);
|
||||
|
||||
$response = $this->getJson('/api/v2/search?q=searchable&type=accounts');
|
||||
$response->assertOk();
|
||||
|
||||
$accounts = $response->json('accounts');
|
||||
$usernames = collect($accounts)->pluck('username')->toArray();
|
||||
expect($usernames)->toContain('searchable');
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
uses(LazilyRefreshDatabase::class);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Compose Tests
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
describe('compose page', function () {
|
||||
it('loads for authenticated user', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
|
||||
$this->actingAs($user)
|
||||
->get('/i/compose')
|
||||
->assertOk();
|
||||
});
|
||||
|
||||
it('requires authentication', function () {
|
||||
$this->get('/i/compose')
|
||||
->assertStatus(403);
|
||||
});
|
||||
});
|
||||
|
||||
describe('compose settings', function () {
|
||||
it('returns compose settings for authenticated user', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
|
||||
$this->actingAs($user)
|
||||
->getJson('/api/compose/v0/settings')
|
||||
->assertOk()
|
||||
->assertJsonStructure(['max_altext_length']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('media upload', function () {
|
||||
it('rejects upload without file', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
|
||||
$this->actingAs($user)
|
||||
->postJson('/api/compose/v0/media/upload', [])
|
||||
->assertUnprocessable();
|
||||
});
|
||||
|
||||
it('rejects file exceeding max size', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
$maxSize = (int) config('pixelfed.max_photo_size', 15000);
|
||||
|
||||
// Create a file larger than max
|
||||
$file = UploadedFile::fake()->create('large.jpg', $maxSize + 1000, 'image/jpeg');
|
||||
|
||||
$this->actingAs($user)
|
||||
->postJson('/api/compose/v0/media/upload', [
|
||||
'file' => $file,
|
||||
])
|
||||
->assertUnprocessable();
|
||||
});
|
||||
|
||||
it('rejects unsupported file types', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
|
||||
$file = UploadedFile::fake()->create('document.pdf', 100, 'application/pdf');
|
||||
|
||||
$this->actingAs($user)
|
||||
->postJson('/api/compose/v0/media/upload', [
|
||||
'file' => $file,
|
||||
])
|
||||
->assertUnprocessable();
|
||||
});
|
||||
});
|
||||
|
||||
describe('hashtag autocomplete', function () {
|
||||
it('returns results for hashtag search', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
|
||||
$this->actingAs($user)
|
||||
->getJson('/api/compose/v0/search/tag?q=pixel')
|
||||
->assertOk()
|
||||
->assertJsonIsArray();
|
||||
});
|
||||
|
||||
it('rejects empty query', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->refresh();
|
||||
|
||||
$this->actingAs($user)
|
||||
->getJson('/api/compose/v0/search/tag?q=')
|
||||
->assertStatus(422);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue