mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-08 08:12:17 +01:00
Updated invitation flow, Moved jetstream function to REST endpoints; Lower case email
This commit is contained in:
committed by
Constantin Graf
parent
d732064f31
commit
a30d192ea2
@@ -5,9 +5,15 @@ declare(strict_types=1);
|
||||
namespace Tests\Unit\Endpoint\Api\V1;
|
||||
|
||||
use App\Enums\Role;
|
||||
use App\Events\AfterCreateOrganization;
|
||||
use App\Http\Controllers\Api\V1\OrganizationController;
|
||||
use App\Models\Member;
|
||||
use App\Models\Organization;
|
||||
use App\Service\BillableRateService;
|
||||
use App\Service\IpLookup\IpLookupResponseDto;
|
||||
use App\Service\IpLookup\IpLookupServiceContract;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Laravel\Passport\Passport;
|
||||
use Mockery\MockInterface;
|
||||
use PHPUnit\Framework\Attributes\UsesClass;
|
||||
@@ -93,6 +99,121 @@ class OrganizationEndpointTest extends ApiEndpointTestAbstract
|
||||
$response->assertJsonPath('data.billable_rate', null);
|
||||
}
|
||||
|
||||
public function test_store_endpoint_creates_new_organization(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission();
|
||||
$organizationFake = Organization::factory()->make();
|
||||
Event::fake([
|
||||
AfterCreateOrganization::class,
|
||||
]);
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->postJson(route('api.v1.organizations.store'), [
|
||||
'name' => $organizationFake->name,
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertStatus(201);
|
||||
$response->assertJson(fn (AssertableJson $json) => $json
|
||||
->has('data')
|
||||
->where('data.name', $organizationFake->name)
|
||||
->where('data.is_personal', false)
|
||||
->where('data.currency', config('app.localization.default_currency'))
|
||||
->etc()
|
||||
);
|
||||
|
||||
/** @var Organization $newOrganization */
|
||||
$newOrganization = Organization::query()->where('name', $organizationFake->name)->firstOrFail();
|
||||
$this->assertTrue($newOrganization->owner->is($data->user));
|
||||
$this->assertSame($newOrganization->getKey(), $data->user->fresh()->current_team_id);
|
||||
$this->assertDatabaseHas(Member::class, [
|
||||
'organization_id' => $newOrganization->getKey(),
|
||||
'user_id' => $data->user->getKey(),
|
||||
'role' => Role::Owner->value,
|
||||
]);
|
||||
Event::assertDispatched(AfterCreateOrganization::class, function (AfterCreateOrganization $event) use ($newOrganization): bool {
|
||||
return $event->organization->is($newOrganization);
|
||||
});
|
||||
}
|
||||
|
||||
public function test_store_endpoint_uses_ip_lookup_currency_for_new_organization(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission();
|
||||
$this->mock(IpLookupServiceContract::class, function (MockInterface $mock): void {
|
||||
$mock->shouldReceive('lookup')
|
||||
->once()
|
||||
->andReturn(new IpLookupResponseDto(null, null, 'USD'));
|
||||
});
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->postJson(route('api.v1.organizations.store'), [
|
||||
'name' => 'Test Organization',
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertStatus(201);
|
||||
$response->assertJsonPath('data.currency', 'USD');
|
||||
$this->assertDatabaseHas(Organization::class, [
|
||||
'name' => 'Test Organization',
|
||||
'currency' => 'USD',
|
||||
'user_id' => $data->user->getKey(),
|
||||
'personal_team' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_store_endpoint_fails_if_name_is_missing(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission();
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->postJson(route('api.v1.organizations.store'), []);
|
||||
|
||||
// Assert
|
||||
$response->assertStatus(422);
|
||||
$response->assertJsonValidationErrors(['name']);
|
||||
$this->assertDatabaseCount(Organization::class, 1);
|
||||
}
|
||||
|
||||
public function test_store_endpoint_fails_if_name_is_not_a_string(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission();
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->postJson(route('api.v1.organizations.store'), [
|
||||
'name' => ['Test Organization'],
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertStatus(422);
|
||||
$response->assertJsonValidationErrors(['name']);
|
||||
$this->assertDatabaseCount(Organization::class, 1);
|
||||
}
|
||||
|
||||
public function test_store_endpoint_fails_if_name_is_too_long(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission();
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->postJson(route('api.v1.organizations.store'), [
|
||||
'name' => str_repeat('a', 256),
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertStatus(422);
|
||||
$response->assertJsonValidationErrors(['name']);
|
||||
$this->assertDatabaseCount(Organization::class, 1);
|
||||
}
|
||||
|
||||
public function test_update_endpoint_fails_if_user_has_no_permission_to_update_organizations(): void
|
||||
{
|
||||
// Arrange
|
||||
@@ -260,4 +381,51 @@ class OrganizationEndpointTest extends ApiEndpointTestAbstract
|
||||
'billable_rate' => $organizationFake->billable_rate,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_delete_endpoint_if_user_does_not_have_permission(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission();
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->deleteJson(route('api.v1.organizations.destroy', [$data->organization->getKey()]));
|
||||
|
||||
// Assert
|
||||
$response->assertForbidden();
|
||||
}
|
||||
|
||||
public function test_delete_endpoint_fails_with_not_found_if_id_is_not_uuid(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission([
|
||||
'organizations:delete',
|
||||
]);
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->deleteJson(route('api.v1.organizations.destroy', ['not-uuid']));
|
||||
|
||||
// Assert
|
||||
$response->assertNotFound();
|
||||
}
|
||||
|
||||
public function test_delete_endpoint_can_delete_organization(): void
|
||||
{
|
||||
// Arrange
|
||||
$this->mockPrivateStorage();
|
||||
$data = $this->createUserWithPermission([
|
||||
'organizations:delete',
|
||||
]);
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->deleteJson(route('api.v1.organizations.destroy', [$data->organization->getKey()]));
|
||||
|
||||
// Assert
|
||||
$response->assertNoContent();
|
||||
$this->assertDatabaseMissing(Organization::class, [
|
||||
'id' => $data->organization->getKey(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Endpoint\Api\V1;
|
||||
|
||||
use App\Models\User;
|
||||
use Laravel\Passport\Passport;
|
||||
|
||||
class UserEndpointTest extends ApiEndpointTestAbstract
|
||||
@@ -40,4 +41,57 @@ class UserEndpointTest extends ApiEndpointTestAbstract
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_delete_fails_if_given_user_is_not_the_authenticated_user(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission();
|
||||
$otherData = $this->createUserWithPermission();
|
||||
Passport::actingAs($otherData->user);
|
||||
|
||||
// Act
|
||||
$response = $this->deleteJson(route('api.v1.users.destroy', $data->user->getKey()));
|
||||
|
||||
// Assert
|
||||
$response->assertForbidden();
|
||||
}
|
||||
|
||||
public function test_delete_fails_if_not_authenticated(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission();
|
||||
|
||||
// Act
|
||||
$response = $this->deleteJson(route('api.v1.users.destroy', $data->user->getKey()));
|
||||
|
||||
// Assert
|
||||
$response->assertUnauthorized();
|
||||
}
|
||||
|
||||
public function test_delete_fails_if_user_does_not_exist(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission();
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->deleteJson(route('api.v1.users.destroy', 'not-valid'));
|
||||
|
||||
// Assert
|
||||
$response->assertNotFound();
|
||||
}
|
||||
|
||||
public function test_delete_removes_user(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission();
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->deleteJson(route('api.v1.users.destroy', $data->user->getKey()));
|
||||
|
||||
// Assert
|
||||
$response->assertNoContent();
|
||||
$this->assertDatabaseMissing(User::class, ['id' => $data->user->getKey()]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user