storing analytics data
This commit is contained in:
136
tests/Feature/Discovery/ActivityEventRecordingTest.php
Normal file
136
tests/Feature/Discovery/ActivityEventRecordingTest.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Models\ActivityEvent;
|
||||
use App\Models\Artwork;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
// ── ActivityEvent::record() factory helper ────────────────────────────────────
|
||||
|
||||
it('creates a db row via record()', function () {
|
||||
$user = User::factory()->create();
|
||||
$artwork = Artwork::factory()->create();
|
||||
|
||||
ActivityEvent::record(
|
||||
actorId: $user->id,
|
||||
type: ActivityEvent::TYPE_FAVORITE,
|
||||
targetType: ActivityEvent::TARGET_ARTWORK,
|
||||
targetId: $artwork->id,
|
||||
meta: ['source' => 'test'],
|
||||
);
|
||||
|
||||
$this->assertDatabaseHas('activity_events', [
|
||||
'actor_id' => $user->id,
|
||||
'type' => 'favorite',
|
||||
'target_type' => 'artwork',
|
||||
'target_id' => $artwork->id,
|
||||
]);
|
||||
});
|
||||
|
||||
it('stores all five event types without error', function () {
|
||||
$user = User::factory()->create();
|
||||
$artwork = Artwork::factory()->create();
|
||||
|
||||
$events = [
|
||||
[ActivityEvent::TYPE_UPLOAD, ActivityEvent::TARGET_ARTWORK, $artwork->id],
|
||||
[ActivityEvent::TYPE_COMMENT, ActivityEvent::TARGET_ARTWORK, $artwork->id],
|
||||
[ActivityEvent::TYPE_FAVORITE, ActivityEvent::TARGET_ARTWORK, $artwork->id],
|
||||
[ActivityEvent::TYPE_AWARD, ActivityEvent::TARGET_ARTWORK, $artwork->id],
|
||||
[ActivityEvent::TYPE_FOLLOW, ActivityEvent::TARGET_USER, $user->id],
|
||||
];
|
||||
|
||||
foreach ($events as [$type, $targetType, $targetId]) {
|
||||
ActivityEvent::record($user->id, $type, $targetType, $targetId);
|
||||
}
|
||||
|
||||
expect(ActivityEvent::where('actor_id', $user->id)->count())->toBe(5);
|
||||
});
|
||||
|
||||
it('created_at is populated on the returned instance', function () {
|
||||
$user = User::factory()->create();
|
||||
$artwork = Artwork::factory()->create();
|
||||
|
||||
$event = ActivityEvent::record(
|
||||
$user->id,
|
||||
ActivityEvent::TYPE_COMMENT,
|
||||
ActivityEvent::TARGET_ARTWORK,
|
||||
$artwork->id,
|
||||
);
|
||||
|
||||
expect($event->created_at)->not->toBeNull();
|
||||
});
|
||||
|
||||
it('actor relation resolves after record()', function () {
|
||||
$user = User::factory()->create();
|
||||
$artwork = Artwork::factory()->create();
|
||||
|
||||
$event = ActivityEvent::record($user->id, ActivityEvent::TYPE_UPLOAD, ActivityEvent::TARGET_ARTWORK, $artwork->id);
|
||||
|
||||
expect($event->actor->id)->toBe($user->id);
|
||||
});
|
||||
|
||||
it('meta is null when empty array is passed', function () {
|
||||
$user = User::factory()->create();
|
||||
$artwork = Artwork::factory()->create();
|
||||
|
||||
$event = ActivityEvent::record($user->id, ActivityEvent::TYPE_UPLOAD, ActivityEvent::TARGET_ARTWORK, $artwork->id);
|
||||
|
||||
expect($event->meta)->toBeNull();
|
||||
});
|
||||
|
||||
it('meta is stored when non-empty array is passed', function () {
|
||||
$user = User::factory()->create();
|
||||
$artwork = Artwork::factory()->create();
|
||||
|
||||
$event = ActivityEvent::record(
|
||||
$user->id,
|
||||
ActivityEvent::TYPE_AWARD,
|
||||
ActivityEvent::TARGET_ARTWORK,
|
||||
$artwork->id,
|
||||
['medal' => 'gold'],
|
||||
);
|
||||
|
||||
expect($event->meta)->toBe(['medal' => 'gold']);
|
||||
});
|
||||
|
||||
// ── Community activity feed route ─────────────────────────────────────────────
|
||||
|
||||
it('global activity feed returns 200 for guests', function () {
|
||||
$this->get('/community/activity')->assertStatus(200);
|
||||
});
|
||||
|
||||
it('following tab returns 200 for users with no follows', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAs($user)
|
||||
->get('/community/activity?type=following')
|
||||
->assertStatus(200);
|
||||
});
|
||||
|
||||
it('following tab shows only events from followed users', function () {
|
||||
$user = User::factory()->create();
|
||||
$creator = User::factory()->create();
|
||||
$other = User::factory()->create();
|
||||
$artwork = Artwork::factory()->create();
|
||||
|
||||
// user_followers has no updated_at column
|
||||
DB::table('user_followers')->insert([
|
||||
'user_id' => $creator->id,
|
||||
'follower_id' => $user->id,
|
||||
'created_at' => now(),
|
||||
]);
|
||||
|
||||
// Event from followed creator
|
||||
ActivityEvent::record($creator->id, ActivityEvent::TYPE_UPLOAD, ActivityEvent::TARGET_ARTWORK, $artwork->id);
|
||||
// Event from non-followed user (should not appear)
|
||||
ActivityEvent::record($other->id, ActivityEvent::TYPE_UPLOAD, ActivityEvent::TARGET_ARTWORK, $artwork->id);
|
||||
|
||||
$response = $this->actingAs($user)->get('/community/activity?type=following');
|
||||
$response->assertStatus(200);
|
||||
|
||||
$events = $response->original->gatherData()['events'];
|
||||
expect($events->total())->toBe(1);
|
||||
expect($events->first()->actor_id)->toBe($creator->id);
|
||||
});
|
||||
Reference in New Issue
Block a user