Files
coolify/tests/Feature/DeleteEnvironmentTeamScopingTest.php
T
Andras BacsaiandClaude Opus 5.5 a70e856882 test: remove tests that do not test behavior and strengthen weak ones
- Remove tests that only check markup, CSS, static text, wire:key strings,
  framework behavior, copied app logic, or expect(true)
- Replace source-grep and Reflection checks of security fixes with tests
  that run the real code (shell quoting, locked properties, 403 checks,
  webhook fork trust, log redaction, Sentinel token cleanup)
- Assert response bodies and unchanged data on API error paths
- Run the Traefik version job through handle() instead of private methods
- Update stale tests for scheduled task props, the default Postgres image,
  and the disabled transfer link of unvalidated servers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 08:47:56 +01:00

83 lines
3.4 KiB
PHP

<?php
use App\Livewire\Project\DeleteEnvironment;
use App\Models\Application;
use App\Models\Environment;
use App\Models\InstanceSettings;
use App\Models\Project;
use App\Models\Team;
use App\Models\User;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Features\SupportLockedProperties\CannotUpdateLockedPropertyException;
use Livewire\Livewire;
uses(RefreshDatabase::class);
beforeEach(function () {
InstanceSettings::unguarded(fn () => InstanceSettings::query()->create(['id' => 0]));
// Current team
$this->userA = User::factory()->create();
$this->teamA = Team::factory()->create();
$this->userA->teams()->attach($this->teamA, ['role' => 'owner']);
$this->projectA = Project::factory()->create(['team_id' => $this->teamA->id]);
$this->environmentA = Environment::factory()->create(['project_id' => $this->projectA->id]);
// Another team
$this->userB = User::factory()->create();
$this->teamB = Team::factory()->create();
$this->userB->teams()->attach($this->teamB, ['role' => 'owner']);
$this->projectB = Project::factory()->create(['team_id' => $this->teamB->id]);
$this->environmentB = Environment::factory()->create(['project_id' => $this->projectB->id]);
$this->actingAs($this->userA);
session(['currentTeam' => $this->teamA]);
});
test('mount cannot load DeleteEnvironment with environment from another team', function () {
Livewire::test(DeleteEnvironment::class, ['environment_id' => $this->environmentB->id]);
})->throws(ModelNotFoundException::class);
test('mount can load DeleteEnvironment with own team environment', function () {
$component = Livewire::test(DeleteEnvironment::class, ['environment_id' => $this->environmentA->id]);
expect($component->get('environmentName'))->toBe($this->environmentA->name);
});
test('environment_id is locked and cannot be reassigned from the client', function () {
Livewire::test(DeleteEnvironment::class, ['environment_id' => $this->environmentA->id])
->set('environment_id', $this->environmentB->id);
})->throws(CannotUpdateLockedPropertyException::class);
test('delete still removes an empty environment owned by the current team', function () {
$component = Livewire::test(DeleteEnvironment::class, ['environment_id' => $this->environmentA->id])
->set('parameters', ['project_uuid' => $this->projectA->uuid]);
$component->call('delete');
expect(Environment::find($this->environmentA->id))->toBeNull();
});
test('delete cannot resolve a non-empty environment from another team', function () {
// The team-scoped lookup must stay in the delete() path so the
// "has defined resources" branch can never run for an environment
// outside the caller's team.
Application::factory()->create([
'environment_id' => $this->environmentB->id,
]);
$teamScopedLookup = fn () => Environment::ownedByCurrentTeam()
->findOrFail($this->environmentB->id);
expect($teamScopedLookup)->toThrow(ModelNotFoundException::class);
});
test('team scoped lookup permits own team environment', function () {
// Positive case so the cross-team check above cannot pass merely
// because the helper itself is broken.
$found = Environment::ownedByCurrentTeam()->findOrFail($this->environmentA->id);
expect($found->id)->toBe($this->environmentA->id);
});