mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-06-06 20:37:32 +00:00
162 lines
6.9 KiB
PHP
162 lines
6.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Unit\Console\Commands\SelfHost;
|
|
|
|
use App\Console\Commands\SelfHost\SelfHostDatabaseConsistency;
|
|
use App\Enums\Role;
|
|
use App\Models\Client;
|
|
use App\Models\Organization;
|
|
use App\Models\Project;
|
|
use App\Models\Task;
|
|
use App\Models\TimeEntry;
|
|
use App\Models\User;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\Artisan;
|
|
use PHPUnit\Framework\Attributes\CoversClass;
|
|
use Tests\TestCaseWithDatabase;
|
|
|
|
#[CoversClass(SelfHostDatabaseConsistency::class)]
|
|
class SelfHostDatabaseConsistencyCommandTest extends TestCaseWithDatabase
|
|
{
|
|
public function test_checks_that_task_need_to_be_part_of_project_in_time_entries(): void
|
|
{
|
|
// Arrange
|
|
$user = $this->createUserWithRole(Role::Owner);
|
|
$project1 = Project::factory()->forOrganization($user->organization)->create();
|
|
$project2 = Project::factory()->forOrganization($user->organization)->create();
|
|
$task = Task::factory()->forOrganization($user->organization)->forProject($project1)->create();
|
|
$timeEntry = TimeEntry::factory()->forMember($user->member)->forTask($task)->forProject($project2)->create();
|
|
|
|
// Act
|
|
$exitCode = $this->withoutMockingConsoleOutput()->artisan('self-host:database-consistency');
|
|
|
|
// Assert
|
|
$this->assertSame(Command::FAILURE, $exitCode);
|
|
$output = Artisan::output();
|
|
$this->assertSame("Consistency problem: Time entries have a task that does not belong to the project of the time entry\n - ".$timeEntry->getKey()."\n", $output);
|
|
}
|
|
|
|
public function test_checks_that_client_id_is_the_client_id_of_the_project(): void
|
|
{
|
|
// Arrange
|
|
$user = $this->createUserWithRole(Role::Owner);
|
|
$client1 = Client::factory()->forOrganization($user->organization)->create();
|
|
$client2 = Client::factory()->forOrganization($user->organization)->create();
|
|
$project = Project::factory()->forOrganization($user->organization)->forClient($client1)->create();
|
|
$timeEntry = TimeEntry::factory()->forMember($user->member)->forProject($project)->create([
|
|
'client_id' => $client2->id,
|
|
]);
|
|
|
|
// Act
|
|
$exitCode = $this->withoutMockingConsoleOutput()->artisan('self-host:database-consistency');
|
|
|
|
// Assert
|
|
$this->assertSame(Command::FAILURE, $exitCode);
|
|
$output = Artisan::output();
|
|
$this->assertSame("Consistency problem: Time entries have a client that does not match the client of the project\n - ".$timeEntry->getKey()."\n", $output);
|
|
}
|
|
|
|
public function test_checks_that_client_id_is_the_client_id_of_the_project_with_no_client_in_time_entry(): void
|
|
{
|
|
// Arrange
|
|
$user = $this->createUserWithRole(Role::Owner);
|
|
$client1 = Client::factory()->forOrganization($user->organization)->create();
|
|
$client2 = Client::factory()->forOrganization($user->organization)->create();
|
|
$project = Project::factory()->forOrganization($user->organization)->forClient($client1)->create();
|
|
$timeEntry = TimeEntry::factory()->forMember($user->member)->forProject($project)->create([
|
|
'client_id' => null,
|
|
]);
|
|
|
|
// Act
|
|
$exitCode = $this->withoutMockingConsoleOutput()->artisan('self-host:database-consistency');
|
|
|
|
// Assert
|
|
$this->assertSame(Command::FAILURE, $exitCode);
|
|
$output = Artisan::output();
|
|
$this->assertSame("Consistency problem: Time entries have a client that does not match the client of the project\n - ".$timeEntry->getKey()."\n", $output);
|
|
}
|
|
|
|
public function test_checks_that_client_id_is_only_null_if_project_is_also_null(): void
|
|
{
|
|
// Arrange
|
|
$user = $this->createUserWithRole(Role::Owner);
|
|
$client1 = Client::factory()->forOrganization($user->organization)->create();
|
|
$project = Project::factory()->forOrganization($user->organization)->forClient($client1)->create();
|
|
$timeEntry = TimeEntry::factory()->forMember($user->member)->create([
|
|
'client_id' => $client1->getKey(),
|
|
]);
|
|
|
|
// Act
|
|
$exitCode = $this->withoutMockingConsoleOutput()->artisan('self-host:database-consistency');
|
|
|
|
// Assert
|
|
$this->assertSame(Command::FAILURE, $exitCode);
|
|
$output = Artisan::output();
|
|
$this->assertSame("Consistency problem: Time entries have a client but no project\n - ".$timeEntry->getKey()."\n", $output);
|
|
}
|
|
|
|
public function test_checks_that_every_user_needs_to_be_a_member_of_at_least_one_organization(): void
|
|
{
|
|
// Arrange
|
|
$user = User::factory()->create();
|
|
|
|
// Act
|
|
$exitCode = $this->withoutMockingConsoleOutput()->artisan('self-host:database-consistency');
|
|
|
|
// Assert
|
|
$this->assertSame(Command::FAILURE, $exitCode);
|
|
$output = Artisan::output();
|
|
$this->assertSame("Consistency problem: Users are not member of any organization\n - ".$user->getKey()."\n", $output);
|
|
}
|
|
|
|
public function test_checks_that_every_organization_needs_at_least_an_owner(): void
|
|
{
|
|
// Arrange
|
|
$user = $this->createUserWithRole(Role::Owner);
|
|
$organization = Organization::factory()->withOwner($user->user)->create();
|
|
|
|
// Act
|
|
$exitCode = $this->withoutMockingConsoleOutput()->artisan('self-host:database-consistency');
|
|
|
|
// Assert
|
|
$this->assertSame(Command::FAILURE, $exitCode);
|
|
$output = Artisan::output();
|
|
$this->assertSame("Consistency problem: Organizations without an owner\n - ".$organization->getKey()."\n", $output);
|
|
}
|
|
|
|
public function test_checks_that_every_member_can_only_have_one_running_time_entry(): void
|
|
{
|
|
// Arrange
|
|
$user = $this->createUserWithRole(Role::Owner);
|
|
$timeEntry1 = TimeEntry::factory()->forMember($user->member)->active()->create();
|
|
$timeEntry2 = TimeEntry::factory()->forMember($user->member)->active()->create();
|
|
|
|
// Act
|
|
$exitCode = $this->withoutMockingConsoleOutput()->artisan('self-host:database-consistency');
|
|
|
|
// Assert
|
|
$this->assertSame(Command::FAILURE, $exitCode);
|
|
$output = Artisan::output();
|
|
$this->assertSame("Consistency problem: Users with more than one running time entry\n - ".$user->user->getKey()."\n", $output);
|
|
}
|
|
|
|
public function test_checks_that_users_have_a_current_organization_that_they_are_not_a_member_of(): void
|
|
{
|
|
// Arrange
|
|
$user1 = $this->createUserWithRole(Role::Owner);
|
|
$user2 = $this->createUserWithRole(Role::Owner);
|
|
$user1->user->currentOrganization()->associate($user2->organization);
|
|
$user1->user->save();
|
|
|
|
// Act
|
|
$exitCode = $this->withoutMockingConsoleOutput()->artisan('self-host:database-consistency');
|
|
|
|
// Assert
|
|
$this->assertSame(Command::FAILURE, $exitCode);
|
|
$output = Artisan::output();
|
|
$this->assertSame("Consistency problem: Users have a current organization that they are not a member of\n - ".$user1->user->getKey()."\n", $output);
|
|
}
|
|
}
|