Implement creator studio and upload updates
This commit is contained in:
145
tests/Feature/Console/ScanContentModerationCommandTest.php
Normal file
145
tests/Feature/Console/ScanContentModerationCommandTest.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Enums\ModerationContentType;
|
||||
use App\Models\ContentModerationActionLog;
|
||||
use App\Models\Artwork;
|
||||
use App\Models\ArtworkComment;
|
||||
use App\Models\ContentModerationFinding;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Log\Events\MessageLogged;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('scans artwork comments and descriptions and stores suspicious findings', function (): void {
|
||||
$artwork = Artwork::factory()->create([
|
||||
'description' => 'Buy followers at https://promo.pornsite.com and win a crypto giveaway now',
|
||||
]);
|
||||
|
||||
ArtworkComment::factory()->create([
|
||||
'artwork_id' => $artwork->id,
|
||||
'user_id' => $artwork->user_id,
|
||||
'content' => 'Visit my site at https://promo.pornsite.com now',
|
||||
'raw_content' => 'Visit my site at https://promo.pornsite.com now',
|
||||
]);
|
||||
|
||||
$code = Artisan::call('skinbase:scan-content-moderation');
|
||||
|
||||
expect($code)->toBe(0)
|
||||
->and(ContentModerationFinding::query()->count())->toBe(2)
|
||||
->and(ContentModerationFinding::query()->where('content_type', ModerationContentType::ArtworkComment)->exists())->toBeTrue()
|
||||
->and(ContentModerationFinding::query()->where('content_type', ModerationContentType::ArtworkDescription)->exists())->toBeTrue();
|
||||
});
|
||||
|
||||
it('does not create duplicate findings for unchanged content', function (): void {
|
||||
$artwork = Artwork::factory()->create([
|
||||
'description' => 'Buy followers at https://promo.pornsite.com and win a crypto giveaway now',
|
||||
]);
|
||||
|
||||
Artisan::call('skinbase:scan-content-moderation', ['--only' => 'descriptions']);
|
||||
Artisan::call('skinbase:scan-content-moderation', ['--only' => 'descriptions']);
|
||||
|
||||
expect(ContentModerationFinding::query()->where('content_type', ModerationContentType::ArtworkDescription)->count())->toBe(1)
|
||||
->and(ContentModerationFinding::query()->first()?->content_id)->toBe($artwork->id);
|
||||
});
|
||||
|
||||
it('supports dry runs without persisting findings', function (): void {
|
||||
Artwork::factory()->create([
|
||||
'description' => 'Buy followers at https://promo.pornsite.com and win a crypto giveaway now',
|
||||
]);
|
||||
|
||||
$code = Artisan::call('skinbase:scan-content-moderation', ['--dry-run' => true]);
|
||||
|
||||
expect($code)->toBe(0)
|
||||
->and(ContentModerationFinding::query()->count())->toBe(0);
|
||||
});
|
||||
|
||||
it('logs a command summary after scanning', function (): void {
|
||||
Event::fake([MessageLogged::class]);
|
||||
|
||||
Artwork::factory()->create([
|
||||
'description' => 'Buy followers at https://promo.pornsite.com and win a crypto giveaway now',
|
||||
]);
|
||||
|
||||
$code = Artisan::call('skinbase:scan-content-moderation', ['--only' => 'descriptions']);
|
||||
|
||||
expect($code)->toBe(0);
|
||||
|
||||
Event::assertDispatched(MessageLogged::class, function (MessageLogged $event): bool {
|
||||
return $event->level === 'info'
|
||||
&& $event->message === 'Content moderation scan complete.'
|
||||
&& ($event->context['targets'] ?? []) === ['artwork_description']
|
||||
&& ($event->context['counts']['scanned'] ?? 0) === 1
|
||||
&& ($event->context['counts']['flagged'] ?? 0) === 1;
|
||||
});
|
||||
});
|
||||
|
||||
it('shows target progress and verbose finding details while scanning', function (): void {
|
||||
Artwork::factory()->create([
|
||||
'description' => 'Buy followers at https://promo.pornsite.com and win a crypto giveaway now',
|
||||
]);
|
||||
|
||||
$code = Artisan::call('skinbase:scan-content-moderation', [
|
||||
'--only' => 'descriptions',
|
||||
'--verbose' => true,
|
||||
]);
|
||||
|
||||
$output = Artisan::output();
|
||||
|
||||
expect($code)->toBe(0)
|
||||
->and($output)->toContain('Starting content moderation scan...')
|
||||
->and($output)->toContain('Scanning Artwork Description entries...')
|
||||
->and($output)->toContain('[artwork_description #')
|
||||
->and($output)->toContain('flagged')
|
||||
->and($output)->toContain('Finished Artwork Description: scanned=1, flagged=1');
|
||||
});
|
||||
|
||||
it('auto hides critical comment spam while keeping the finding', function (): void {
|
||||
$artwork = Artwork::factory()->create();
|
||||
$comment = ArtworkComment::factory()->create([
|
||||
'artwork_id' => $artwork->id,
|
||||
'user_id' => $artwork->user_id,
|
||||
'content' => 'Buy followers now at https://promo.pornsite.com and claim your crypto giveaway',
|
||||
'raw_content' => 'Buy followers now at https://promo.pornsite.com and claim your crypto giveaway',
|
||||
'is_approved' => true,
|
||||
]);
|
||||
|
||||
$code = Artisan::call('skinbase:scan-content-moderation', ['--only' => 'comments']);
|
||||
|
||||
$finding = ContentModerationFinding::query()->where('content_type', ModerationContentType::ArtworkComment)->first();
|
||||
|
||||
expect($code)->toBe(0)
|
||||
->and($finding)->not->toBeNull()
|
||||
->and($finding?->is_auto_hidden)->toBeTrue()
|
||||
->and($finding?->action_taken)->toBe('auto_hide_comment')
|
||||
->and($comment->fresh()->is_approved)->toBeFalse();
|
||||
});
|
||||
|
||||
it('rescans existing findings with the latest rules', function (): void {
|
||||
$artwork = Artwork::factory()->create([
|
||||
'description' => 'Buy followers at https://promo.pornsite.com and win a crypto giveaway now',
|
||||
]);
|
||||
|
||||
$finding = ContentModerationFinding::query()->create([
|
||||
'content_type' => ModerationContentType::ArtworkDescription->value,
|
||||
'content_id' => $artwork->id,
|
||||
'artwork_id' => $artwork->id,
|
||||
'user_id' => $artwork->user_id,
|
||||
'status' => 'pending',
|
||||
'severity' => 'high',
|
||||
'score' => 90,
|
||||
'content_hash' => hash('sha256', 'old-hash'),
|
||||
'scanner_version' => '1.0',
|
||||
'content_snapshot' => 'old snapshot',
|
||||
]);
|
||||
|
||||
$code = Artisan::call('skinbase:rescan-content-moderation', ['--only' => 'descriptions']);
|
||||
$scannerVersion = (string) config('content_moderation.scanner_version');
|
||||
|
||||
expect($code)->toBe(0)
|
||||
->and(ContentModerationFinding::query()->where('content_type', ModerationContentType::ArtworkDescription)->where('content_id', $artwork->id)->where('scanner_version', $scannerVersion)->exists())->toBeTrue()
|
||||
->and(ContentModerationActionLog::query()->where('action_type', 'rescan')->exists())->toBeTrue();
|
||||
});
|
||||
Reference in New Issue
Block a user