migrants-nt-sec/tests/Feature/MigrantPhotoUpdateTest.php

438 lines
17 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\User;
use App\Models\Person;
use App\Models\Photo;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class MigrantPhotoUpdateTest extends TestCase
{
use RefreshDatabase, WithFaker;
/**
* Set up authentication for each test
*/
protected function setUp(): void
{
parent::setUp();
// Create and authenticate as admin user for all tests
$user = User::factory()->create([
'email' => 'test.admin@example.com',
'is_admin' => true
]);
Sanctum::actingAs($user, ['*']);
}
/**
* Test removing photos during migrant update.
*/
public function test_can_remove_photos_during_migrant_update(): void
{
// Create fake storage disk for testing
Storage::fake('public');
// 1. First create a migrant with multiple photos
// Create test photo files
$photo1 = UploadedFile::fake()->create('photo1.jpg', 100, 'image/jpeg');
$photo2 = UploadedFile::fake()->create('photo2.jpg', 100, 'image/jpeg');
$photo3 = UploadedFile::fake()->create('photo3.jpg', 100, 'image/jpeg');
// Create migrant data
$migrantData = [
'surname' => $this->faker->lastName,
'christian_name' => $this->faker->firstName,
'date_of_birth' => $this->faker->date(),
'place_of_birth' => $this->faker->city,
'occupation' => $this->faker->jobTitle,
'id_card_no' => (string)$this->faker->unique()->randomNumber(6),
'migration' => [
'date_of_arrival_aus' => $this->faker->date(),
'date_of_arrival_nt' => $this->faker->date(),
'arrival_period' => '1950-1960',
],
// Add photos to the request
'photos' => [$photo1, $photo2, $photo3],
'captions' => ['First photo', 'Second photo', 'Third photo'],
'main_photo_index' => 0, // Set the first photo as profile
];
// Make the API request to create a migrant with photos
$response = $this->postJson('/api/migrants', $migrantData);
// Assert the response is successful
$response->assertStatus(201);
// Get the created person ID
$personId = $response->json('data.person.person_id');
// Get all photos for this person
$photos = Photo::where('person_id', $personId)->get();
// Confirm we have 3 photos
$this->assertEquals(3, $photos->count());
// Get IDs of the photos we want to remove
$photoToRemove1 = $photos[1]->id; // Second photo
$photoToRemove2 = $photos[2]->id; // Third photo
// 2. Now update the migrant and remove two photos
// Create an array of photos to remove
$photosToRemove = [$photoToRemove1, $photoToRemove2];
$updateData = [
'surname' => 'Updated Surname',
'remove_photos' => $photosToRemove
];
$response = $this->putJson("/api/migrants/{$personId}", $updateData);
// Assert the response is successful
$response->assertStatus(200)
->assertJson([
'success' => true,
'message' => 'Person updated successfully',
]);
// Assert that only one photo remains (the profile photo)
$this->assertEquals(1, Photo::where('person_id', $personId)->count());
// Assert the removed photos no longer exist in the database
$this->assertDatabaseMissing('photos', ['id' => $photoToRemove1]);
$this->assertDatabaseMissing('photos', ['id' => $photoToRemove2]);
// Check that the remaining photo is still the profile photo
$remainingPhoto = Photo::where('person_id', $personId)->first();
$this->assertTrue($remainingPhoto->is_profile_photo);
$this->assertEquals('First photo', $remainingPhoto->caption);
}
/**
* Test updating migrant with new photos while removing existing ones.
*/
public function test_can_update_migrant_with_new_photos_while_removing_existing(): void
{
// Create fake storage disk for testing
Storage::fake('public');
// 1. First create a migrant with multiple photos
$photo1 = UploadedFile::fake()->create('photo1.jpg', 100, 'image/jpeg');
$photo2 = UploadedFile::fake()->create('photo2.jpg', 100, 'image/jpeg');
$migrantData = [
'surname' => $this->faker->lastName,
'christian_name' => $this->faker->firstName,
'date_of_birth' => $this->faker->date(),
'place_of_birth' => $this->faker->city,
'occupation' => $this->faker->jobTitle,
'id_card_no' => (string)$this->faker->unique()->randomNumber(6),
'photos' => [$photo1, $photo2],
'captions' => ['Photo One', 'Photo Two'],
'main_photo_index' => 0,
];
$response = $this->postJson('/api/migrants', $migrantData);
$response->assertStatus(201);
$personId = $response->json('data.person.person_id');
$photos = Photo::where('person_id', $personId)->get();
$this->assertEquals(2, $photos->count());
// Get ID of the photo we want to remove
$photoToRemove = $photos[1]->id; // Second photo
// 2. Update the migrant: remove one photo, add new ones, and change profile photo
$newPhoto1 = UploadedFile::fake()->create('new1.jpg', 100, 'image/jpeg');
$newPhoto2 = UploadedFile::fake()->create('new2.jpg', 100, 'image/jpeg');
$updateData = [
'christian_name' => 'Updated Name',
'photos' => [$newPhoto1, $newPhoto2],
'captions' => ['New Photo 1', 'New Photo 2'],
'main_photo_index' => 0, // Set the first new photo as profile
'remove_photos' => [$photoToRemove]
];
$response = $this->putJson("/api/migrants/{$personId}", $updateData);
$response->assertStatus(200)
->assertJson([
'success' => true,
'message' => 'Person updated successfully',
]);
// Assert we now have 3 photos (1 original + 2 new - 1 removed)
$this->assertEquals(3, Photo::where('person_id', $personId)->count());
// Assert the removed photo no longer exists
$this->assertDatabaseMissing('photos', ['id' => $photoToRemove]);
// Assert the new profile photo is set correctly
$newPhotos = Photo::where('person_id', $personId)
->where('caption', 'New Photo 1')
->get();
$this->assertEquals(1, $newPhotos->count());
$this->assertTrue($newPhotos->first()->is_profile_photo);
// Assert the old profile photo is no longer the profile
$oldProfilePhoto = Photo::where('person_id', $personId)
->where('caption', 'Photo One')
->first();
$this->assertFalse($oldProfilePhoto->is_profile_photo);
}
/**
* Test that when the profile photo is removed, another photo is set as profile.
*/
public function test_when_profile_photo_is_removed_another_is_set_as_profile(): void
{
// Create fake storage disk for testing
Storage::fake('public');
// 1. First create a migrant with multiple photos
$photo1 = UploadedFile::fake()->create('photo1.jpg', 100, 'image/jpeg');
$photo2 = UploadedFile::fake()->create('photo2.jpg', 100, 'image/jpeg');
$photo3 = UploadedFile::fake()->create('photo3.jpg', 100, 'image/jpeg');
$migrantData = [
'surname' => $this->faker->lastName,
'christian_name' => $this->faker->firstName,
'date_of_birth' => $this->faker->date(),
'place_of_birth' => $this->faker->city,
'occupation' => $this->faker->jobTitle,
'id_card_no' => (string)$this->faker->unique()->randomNumber(6),
'photos' => [$photo1, $photo2, $photo3],
'captions' => ['Photo One', 'Photo Two', 'Photo Three'],
'main_photo_index' => 0, // First photo is profile
];
$response = $this->postJson('/api/migrants', $migrantData);
$response->assertStatus(201);
$personId = $response->json('data.person.person_id');
$photos = Photo::where('person_id', $personId)->get();
// Get ID of the profile photo we want to remove
$profilePhotoId = $photos->where('is_profile_photo', true)->first()->id;
// 2. Update the migrant and remove the profile photo
$updateData = [
'remove_photos' => [$profilePhotoId]
];
$response = $this->putJson("/api/migrants/{$personId}", $updateData);
$response->assertStatus(200);
// Assert we now have 2 photos
$this->assertEquals(2, Photo::where('person_id', $personId)->count());
// Assert that a new profile photo was automatically set
$this->assertEquals(1, Photo::where('person_id', $personId)
->where('is_profile_photo', true)
->count());
// Assert the removed photo no longer exists
$this->assertDatabaseMissing('photos', ['id' => $profilePhotoId]);
}
/**
* Test that removing non-profile photos doesn't affect the profile photo.
*/
public function test_removing_non_profile_photos_preserves_profile_photo(): void
{
// Create fake storage disk for testing
Storage::fake('public');
// 1. First create a migrant with multiple photos
// Create test photo files
$photo1 = UploadedFile::fake()->create('photo1.jpg', 100, 'image/jpeg');
$photo2 = UploadedFile::fake()->create('photo2.jpg', 100, 'image/jpeg');
$photo3 = UploadedFile::fake()->create('photo3.jpg', 100, 'image/jpeg');
// Create migrant data
$migrantData = [
'surname' => $this->faker->lastName,
'christian_name' => $this->faker->firstName,
'date_of_birth' => $this->faker->date(),
'place_of_birth' => $this->faker->city,
'occupation' => $this->faker->jobTitle,
'id_card_no' => (string)$this->faker->unique()->randomNumber(6),
'migration' => [
'date_of_arrival_aus' => $this->faker->date(),
'date_of_arrival_nt' => $this->faker->date(),
'arrival_period' => '1950-1960',
],
// Add photos to the request
'photos' => [$photo1, $photo2, $photo3],
'captions' => ['Profile photo', 'Second photo', 'Third photo'],
'main_photo_index' => 0, // Set the first photo as profile
];
// Make the API request to create a migrant with photos
$response = $this->postJson('/api/migrants', $migrantData);
// Assert the response is successful
$response->assertStatus(201);
// Get the created person ID
$personId = $response->json('data.person.person_id');
// Get all photos for this person
$photos = Photo::where('person_id', $personId)->get();
// Confirm we have 3 photos
$this->assertEquals(3, $photos->count());
// Get the profile photo ID
$profilePhotoId = null;
$photoToRemove1 = null;
$photoToRemove2 = null;
foreach ($photos as $photo) {
if ($photo->is_profile_photo) {
$profilePhotoId = $photo->id;
} else {
if ($photoToRemove1 === null) {
$photoToRemove1 = $photo->id;
} else {
$photoToRemove2 = $photo->id;
}
}
}
// Ensure we have a profile photo and two non-profile photos
$this->assertNotNull($profilePhotoId);
$this->assertNotNull($photoToRemove1);
$this->assertNotNull($photoToRemove2);
// 2. Now update the migrant and remove the non-profile photos
// Create an array of photos to remove
$photosToRemove = [$photoToRemove1, $photoToRemove2];
$updateData = [
'surname' => 'Updated Surname',
'remove_photos' => $photosToRemove
];
$response = $this->putJson("/api/migrants/{$personId}", $updateData);
// Assert the response is successful
$response->assertStatus(200)
->assertJson([
'success' => true,
'message' => 'Person updated successfully',
]);
// Assert that only one photo remains (the profile photo)
$this->assertEquals(1, Photo::where('person_id', $personId)->count());
// Assert the removed photos no longer exist in the database
$this->assertDatabaseMissing('photos', ['id' => $photoToRemove1]);
$this->assertDatabaseMissing('photos', ['id' => $photoToRemove2]);
// Check that the profile photo is still the same and marked as profile
$remainingPhoto = Photo::where('person_id', $personId)->first();
$this->assertEquals($profilePhotoId, $remainingPhoto->id);
$this->assertTrue($remainingPhoto->is_profile_photo);
$this->assertEquals('Profile photo', $remainingPhoto->caption);
}
/**
* Test adding new photos and setting one as the profile photo.
*/
public function test_adding_new_photos_and_setting_as_profile(): void
{
// Create fake storage disk for testing
Storage::fake('public');
// 1. First create a migrant with one photo
// Create test photo file
$initialPhoto = UploadedFile::fake()->create('initial.jpg', 100, 'image/jpeg');
// Create migrant data
$migrantData = [
'surname' => $this->faker->lastName,
'christian_name' => $this->faker->firstName,
'date_of_birth' => $this->faker->date(),
'place_of_birth' => $this->faker->city,
'occupation' => $this->faker->jobTitle,
'id_card_no' => (string)$this->faker->unique()->randomNumber(6),
'migration' => [
'date_of_arrival_aus' => $this->faker->date(),
'date_of_arrival_nt' => $this->faker->date(),
'arrival_period' => '1950-1960',
],
// Add initial photo
'photos' => [$initialPhoto],
'captions' => ['Initial photo'],
'main_photo_index' => 0, // Set as profile
];
// Make the API request to create a migrant with a photo
$response = $this->postJson('/api/migrants', $migrantData);
// Assert the response is successful
$response->assertStatus(201);
// Get the created person ID
$personId = $response->json('data.person.person_id');
// Confirm we have 1 photo and it's the profile photo
$initialPhotos = Photo::where('person_id', $personId)->get();
$this->assertEquals(1, $initialPhotos->count());
$this->assertTrue($initialPhotos[0]->is_profile_photo);
// 2. Now update the migrant with new photos, setting one as profile
$newPhoto1 = UploadedFile::fake()->create('new1.jpg', 100, 'image/jpeg');
$newPhoto2 = UploadedFile::fake()->create('new2.jpg', 100, 'image/jpeg');
$updateData = [
'surname' => 'Updated Surname',
// Add new photos
'photos' => [$newPhoto1, $newPhoto2],
'captions' => ['New photo 1', 'New photo 2 (profile)'],
'main_photo_index' => 1 // Set the second new photo as profile
];
$response = $this->putJson("/api/migrants/{$personId}", $updateData);
// Assert the response is successful
$response->assertStatus(200)
->assertJson([
'success' => true,
'message' => 'Person updated successfully',
]);
// Assert that we now have 3 photos (1 initial + 2 new)
$this->assertEquals(3, Photo::where('person_id', $personId)->count());
// Assert that exactly one photo is marked as profile
$this->assertEquals(1, Photo::where('person_id', $personId)
->where('is_profile_photo', true)
->count());
// Assert that the profile photo is the one we designated
$profilePhoto = Photo::where('person_id', $personId)
->where('is_profile_photo', true)
->first();
$this->assertEquals('New photo 2 (profile)', $profilePhoto->caption);
// Assert that the original photo is no longer the profile photo
$originalPhoto = Photo::where('person_id', $personId)
->where('caption', 'Initial photo')
->first();
$this->assertFalse($originalPhoto->is_profile_photo);
}
}