FMCS location scoping - Added tests

This commit is contained in:
snipe
2026-06-12 17:26:57 +01:00
parent 8ebddd95ff
commit c8ae09cd43
2 changed files with 326 additions and 0 deletions
@@ -0,0 +1,174 @@
<?php
namespace Tests\Feature\Locations\Api;
use App\Models\Company;
use App\Models\Location;
use App\Models\User;
use Tests\TestCase;
/**
* Verifies that a location cannot be given a parent that belongs to a different
* company when FMCS is enabled, and that the check is bypassed when FMCS is off.
*
* The API update case also covers the scenario where only parent_id changes
* (company_id not included in the request), to ensure the check runs regardless.
*/
class LocationParentCompanyTest extends TestCase
{
// -----------------------------------------------------------------------
// store (create)
// -----------------------------------------------------------------------
public function test_cannot_create_location_with_cross_company_parent_when_fmcs_enabled()
{
$this->settings->enableMultipleFullCompanySupport();
$acme = Company::factory()->create(['name' => 'Acme']);
$globex = Company::factory()->create(['name' => 'Globex']);
$parentLocation = Location::factory()->create(['company_id' => $acme->id]);
$this->actingAsForApi(User::factory()->superuser()->create())
->postJson(route('api.locations.store'), [
'name' => 'Location B',
'company_id' => $globex->id,
'parent_id' => $parentLocation->id,
])
->assertOk()
->assertStatusMessageIs('error');
$this->assertFalse(Location::where('name', 'Location B')->exists());
}
public function test_can_create_location_with_same_company_parent_when_fmcs_enabled()
{
$this->settings->enableMultipleFullCompanySupport();
$acme = Company::factory()->create(['name' => 'Acme']);
$parentLocation = Location::factory()->create(['company_id' => $acme->id]);
$this->actingAsForApi(User::factory()->superuser()->create())
->postJson(route('api.locations.store'), [
'name' => 'Location B',
'company_id' => $acme->id,
'parent_id' => $parentLocation->id,
])
->assertOk()
->assertStatusMessageIs('success');
$this->assertTrue(Location::where('name', 'Location B')->exists());
}
public function test_can_create_location_with_cross_company_parent_when_fmcs_disabled()
{
$this->settings->disableMultipleFullCompanySupport();
$acme = Company::factory()->create(['name' => 'Acme']);
$globex = Company::factory()->create(['name' => 'Globex']);
$parentLocation = Location::factory()->create(['company_id' => $acme->id]);
$this->actingAsForApi(User::factory()->superuser()->create())
->postJson(route('api.locations.store'), [
'name' => 'Location B',
'company_id' => $globex->id,
'parent_id' => $parentLocation->id,
])
->assertOk()
->assertStatusMessageIs('success');
$this->assertTrue(Location::where('name', 'Location B')->exists());
}
// -----------------------------------------------------------------------
// update
// -----------------------------------------------------------------------
public function test_cannot_update_location_to_cross_company_parent_when_fmcs_enabled()
{
$this->settings->enableMultipleFullCompanySupport();
$acme = Company::factory()->create(['name' => 'Acme']);
$globex = Company::factory()->create(['name' => 'Globex']);
$parentLocation = Location::factory()->create(['company_id' => $acme->id]);
$location = Location::factory()->create(['name' => 'Location B', 'company_id' => $globex->id]);
$this->actingAsForApi(User::factory()->superuser()->create())
->patchJson(route('api.locations.update', $location), [
'name' => 'Location B',
'company_id' => $globex->id,
'parent_id' => $parentLocation->id,
])
->assertOk()
->assertStatusMessageIs('error');
$this->assertNull($location->fresh()->parent_id);
}
public function test_cannot_update_location_parent_id_only_to_cross_company_parent_when_fmcs_enabled()
{
// Ensures the check fires even when company_id is not included in the request.
$this->settings->enableMultipleFullCompanySupport();
$acme = Company::factory()->create(['name' => 'Acme']);
$globex = Company::factory()->create(['name' => 'Globex']);
$parentLocation = Location::factory()->create(['company_id' => $acme->id]);
$location = Location::factory()->create(['name' => 'Location B', 'company_id' => $globex->id]);
$this->actingAsForApi(User::factory()->superuser()->create())
->patchJson(route('api.locations.update', $location), [
'parent_id' => $parentLocation->id,
])
->assertOk()
->assertStatusMessageIs('error');
$this->assertNull($location->fresh()->parent_id);
}
public function test_can_update_location_to_same_company_parent_when_fmcs_enabled()
{
$this->settings->enableMultipleFullCompanySupport();
$acme = Company::factory()->create(['name' => 'Acme']);
$parentLocation = Location::factory()->create(['company_id' => $acme->id]);
$location = Location::factory()->create(['name' => 'Location B', 'company_id' => $acme->id]);
$this->actingAsForApi(User::factory()->superuser()->create())
->patchJson(route('api.locations.update', $location), [
'name' => 'Location B',
'company_id' => $acme->id,
'parent_id' => $parentLocation->id,
])
->assertOk()
->assertStatusMessageIs('success');
$this->assertEquals($parentLocation->id, $location->fresh()->parent_id);
}
public function test_can_update_location_to_cross_company_parent_when_fmcs_disabled()
{
$this->settings->disableMultipleFullCompanySupport();
$acme = Company::factory()->create(['name' => 'Acme']);
$globex = Company::factory()->create(['name' => 'Globex']);
$parentLocation = Location::factory()->create(['company_id' => $acme->id]);
$location = Location::factory()->create(['name' => 'Location B', 'company_id' => $globex->id]);
$this->actingAsForApi(User::factory()->superuser()->create())
->patchJson(route('api.locations.update', $location), [
'name' => 'Location B',
'company_id' => $globex->id,
'parent_id' => $parentLocation->id,
])
->assertOk()
->assertStatusMessageIs('success');
$this->assertEquals($parentLocation->id, $location->fresh()->parent_id);
}
}
@@ -0,0 +1,152 @@
<?php
namespace Tests\Feature\Locations\Ui;
use App\Models\Company;
use App\Models\Location;
use App\Models\User;
use Tests\TestCase;
/**
* Verifies that a location cannot be given a parent that belongs to a different
* company when FMCS is enabled, and that the check is bypassed when FMCS is off.
*/
class LocationParentCompanyTest extends TestCase
{
// -----------------------------------------------------------------------
// store (create)
// -----------------------------------------------------------------------
public function test_cannot_create_location_with_cross_company_parent_when_fmcs_enabled()
{
$this->settings->enableMultipleFullCompanySupport();
$acme = Company::factory()->create(['name' => 'Acme']);
$globex = Company::factory()->create(['name' => 'Globex']);
$parentLocation = Location::factory()->create(['company_id' => $acme->id]);
$this->actingAs(User::factory()->superuser()->create())
->from(route('locations.create'))
->post(route('locations.store'), [
'name' => 'Location B',
'company_id' => $globex->id,
'parent_id' => $parentLocation->id,
])
->assertRedirect(route('locations.create'))
->assertSessionHas('error');
$this->assertFalse(Location::where('name', 'Location B')->exists());
}
public function test_can_create_location_with_same_company_parent_when_fmcs_enabled()
{
$this->settings->enableMultipleFullCompanySupport();
$acme = Company::factory()->create(['name' => 'Acme']);
$parentLocation = Location::factory()->create(['company_id' => $acme->id]);
$this->actingAs(User::factory()->superuser()->create())
->post(route('locations.store'), [
'name' => 'Location B',
'company_id' => $acme->id,
'parent_id' => $parentLocation->id,
])
->assertRedirect(route('locations.index'))
->assertSessionHasNoErrors();
$this->assertTrue(Location::where('name', 'Location B')->exists());
}
public function test_can_create_location_with_cross_company_parent_when_fmcs_disabled()
{
$this->settings->disableMultipleFullCompanySupport();
$acme = Company::factory()->create(['name' => 'Acme']);
$globex = Company::factory()->create(['name' => 'Globex']);
$parentLocation = Location::factory()->create(['company_id' => $acme->id]);
$this->actingAs(User::factory()->superuser()->create())
->post(route('locations.store'), [
'name' => 'Location B',
'company_id' => $globex->id,
'parent_id' => $parentLocation->id,
])
->assertRedirect(route('locations.index'))
->assertSessionHasNoErrors();
$this->assertTrue(Location::where('name', 'Location B')->exists());
}
// -----------------------------------------------------------------------
// update (edit)
// -----------------------------------------------------------------------
public function test_cannot_update_location_to_cross_company_parent_when_fmcs_enabled()
{
$this->settings->enableMultipleFullCompanySupport();
$acme = Company::factory()->create(['name' => 'Acme']);
$globex = Company::factory()->create(['name' => 'Globex']);
$parentLocation = Location::factory()->create(['company_id' => $acme->id]);
$location = Location::factory()->create(['name' => 'Location B', 'company_id' => $globex->id]);
$this->actingAs(User::factory()->superuser()->create())
->from(route('locations.edit', $location))
->put(route('locations.update', $location), [
'name' => 'Location B',
'company_id' => $globex->id,
'parent_id' => $parentLocation->id,
])
->assertRedirect(route('locations.edit', $location))
->assertSessionHas('error');
$this->assertNull($location->fresh()->parent_id);
}
public function test_can_update_location_to_same_company_parent_when_fmcs_enabled()
{
$this->settings->enableMultipleFullCompanySupport();
$acme = Company::factory()->create(['name' => 'Acme']);
$parentLocation = Location::factory()->create(['company_id' => $acme->id]);
$location = Location::factory()->create(['name' => 'Location B', 'company_id' => $acme->id]);
$this->actingAs(User::factory()->superuser()->create())
->put(route('locations.update', $location), [
'name' => 'Location B',
'company_id' => $acme->id,
'parent_id' => $parentLocation->id,
])
->assertRedirect(route('locations.index'))
->assertSessionHasNoErrors();
$this->assertEquals($parentLocation->id, $location->fresh()->parent_id);
}
public function test_can_update_location_to_cross_company_parent_when_fmcs_disabled()
{
$this->settings->disableMultipleFullCompanySupport();
$acme = Company::factory()->create(['name' => 'Acme']);
$globex = Company::factory()->create(['name' => 'Globex']);
$parentLocation = Location::factory()->create(['company_id' => $acme->id]);
$location = Location::factory()->create(['name' => 'Location B', 'company_id' => $globex->id]);
$this->actingAs(User::factory()->superuser()->create())
->put(route('locations.update', $location), [
'name' => 'Location B',
'company_id' => $globex->id,
'parent_id' => $parentLocation->id,
])
->assertRedirect(route('locations.index'))
->assertSessionHasNoErrors();
$this->assertEquals($parentLocation->id, $location->fresh()->parent_id);
}
}