93 lines
3.5 KiB
PHP
93 lines
3.5 KiB
PHP
<?php
|
|
|
|
use App\Actions\CreateDefaultCategories;
|
|
use App\Models\Account;
|
|
use App\Models\Category;
|
|
use App\Models\Space;
|
|
use App\Models\Transaction;
|
|
use App\Models\User;
|
|
|
|
it('provisions a personal space when a user is created', function () {
|
|
$user = User::factory()->create();
|
|
|
|
expect($user->personalSpace)->not->toBeNull()
|
|
->and($user->personalSpace->personal)->toBeTrue()
|
|
->and($user->current_space_id)->toBe($user->personalSpace->id)
|
|
->and($user->activeSpace()->id)->toBe($user->personalSpace->id);
|
|
});
|
|
|
|
it('stamps owned rows with the owner\'s current space by default', function () {
|
|
$user = User::factory()->create();
|
|
|
|
$account = Account::factory()->for($user)->create();
|
|
|
|
expect($account->space_id)->toBe($user->current_space_id);
|
|
});
|
|
|
|
it('inherits a transaction\'s space from its account, not the acting user', function () {
|
|
$owner = User::factory()->create();
|
|
$account = Account::factory()->for($owner)->create();
|
|
|
|
// A transaction created with a different acting user still lands in the
|
|
// account's space (the account is the tenant anchor).
|
|
$other = User::factory()->create();
|
|
$transaction = Transaction::factory()->for($account)->create(['user_id' => $other->id]);
|
|
|
|
expect($transaction->space_id)->toBe($account->space_id);
|
|
});
|
|
|
|
it('seeds default categories into the given space', function () {
|
|
$user = User::factory()->create();
|
|
|
|
app(CreateDefaultCategories::class)->handle($user);
|
|
|
|
expect(Category::where('space_id', $user->current_space_id)->count())->toBeGreaterThan(0)
|
|
->and(Category::whereNull('space_id')->count())->toBe(0);
|
|
});
|
|
|
|
it('resolves active space back to personal when the pointer is stale', function () {
|
|
$user = User::factory()->create();
|
|
$foreign = Space::factory()->create();
|
|
|
|
// Point the user at a space they cannot access.
|
|
$user->forceFill(['current_space_id' => $foreign->id])->saveQuietly();
|
|
$user->refresh();
|
|
|
|
expect($user->activeSpace()->personal)->toBeTrue()
|
|
->and($user->fresh()->current_space_id)->toBe($user->personalSpace->id);
|
|
});
|
|
|
|
it('backfills legacy rows that predate spaces', function () {
|
|
$user = User::factory()->create();
|
|
$account = Account::factory()->for($user)->create();
|
|
|
|
// Simulate a pre-migration state: no space, dangling pointers.
|
|
Account::query()->where('id', $account->id)->update(['space_id' => null]);
|
|
User::query()->where('id', $user->id)->update(['current_space_id' => null]);
|
|
Space::query()->where('owner_id', $user->id)->delete();
|
|
|
|
$this->artisan('spaces:backfill')->assertSuccessful();
|
|
|
|
$user->refresh();
|
|
expect($user->current_space_id)->not->toBeNull()
|
|
->and($account->fresh()->space_id)->toBe($user->current_space_id);
|
|
});
|
|
|
|
it('backfills soft-deleted users and their rows', function () {
|
|
$user = User::factory()->create();
|
|
$account = Account::factory()->for($user)->create();
|
|
|
|
// Simulate a pre-migration, soft-deleted user with dangling data.
|
|
Account::query()->where('id', $account->id)->update(['space_id' => null]);
|
|
User::query()->where('id', $user->id)->update(['current_space_id' => null]);
|
|
Space::query()->where('owner_id', $user->id)->delete();
|
|
$user->delete();
|
|
|
|
$this->artisan('spaces:backfill')->assertSuccessful();
|
|
|
|
$trashed = User::withTrashed()->find($user->id);
|
|
expect($trashed->trashed())->toBeTrue()
|
|
->and($trashed->current_space_id)->not->toBeNull()
|
|
->and($account->fresh()->space_id)->toBe($trashed->current_space_id);
|
|
});
|