Pest Test Improvements (#1137)
Co-authored-by: Lance Pioch <git@lance.sh> Co-authored-by: RMartinOscar <40749467+RMartinOscar@users.noreply.github.com>
This commit is contained in:
parent
b39a8186ae
commit
2046fa453a
3
.gitignore
vendored
3
.gitignore
vendored
@ -24,8 +24,7 @@ yarn-error.log
|
||||
/.vscode
|
||||
|
||||
public/assets/manifest.json
|
||||
/database/*.sqlite
|
||||
/database/*.sqlite-journal
|
||||
/database/*.sqlite*
|
||||
filament-monaco-editor/
|
||||
_ide_helper*
|
||||
/.phpstorm.meta.php
|
||||
|
@ -14,4 +14,24 @@ enum RolePermissionModels: string
|
||||
case Server = 'server';
|
||||
case User = 'user';
|
||||
case Webhook = 'webhook';
|
||||
|
||||
public function viewAny(): string
|
||||
{
|
||||
return RolePermissionPrefixes::ViewAny->value . ' ' . $this->value;
|
||||
}
|
||||
|
||||
public function view(): string
|
||||
{
|
||||
return RolePermissionPrefixes::View->value . ' ' . $this->value;
|
||||
}
|
||||
|
||||
public function create(): string
|
||||
{
|
||||
return RolePermissionPrefixes::Create->value . ' ' . $this->value;
|
||||
}
|
||||
|
||||
public function update(): string
|
||||
{
|
||||
return RolePermissionPrefixes::Update->value . ' ' . $this->value;
|
||||
}
|
||||
}
|
||||
|
@ -36,26 +36,22 @@ class SettingsController extends ClientApiController
|
||||
$name = $request->input('name');
|
||||
$description = $request->has('description') ? (string) $request->input('description') : $server->description;
|
||||
|
||||
$server->name = $name;
|
||||
|
||||
if (config('panel.editable_server_descriptions')) {
|
||||
$server->description = $description;
|
||||
}
|
||||
|
||||
$server->save();
|
||||
|
||||
if ($server->name !== $name) {
|
||||
Activity::event('server:settings.rename')
|
||||
->property(['old' => $server->name, 'new' => $name])
|
||||
->log();
|
||||
$server->name = $name;
|
||||
}
|
||||
|
||||
if ($server->description !== $description) {
|
||||
if ($server->description !== $description && config('panel.editable_server_descriptions')) {
|
||||
Activity::event('server:settings.description')
|
||||
->property(['old' => $server->description, 'new' => $description])
|
||||
->log();
|
||||
$server->description = $description;
|
||||
}
|
||||
|
||||
$server->save();
|
||||
|
||||
return new JsonResponse([], Response::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
|
@ -4,12 +4,13 @@ namespace App\Models;
|
||||
|
||||
use App\Contracts\Validatable;
|
||||
use App\Traits\HasValidation;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class Permission extends Model implements Validatable
|
||||
{
|
||||
use HasValidation;
|
||||
use HasFactory, HasValidation;
|
||||
|
||||
/**
|
||||
* The resource name for this model when it is transformed into an
|
||||
|
@ -4,6 +4,7 @@ namespace App\Models;
|
||||
|
||||
use App\Enums\RolePermissionModels;
|
||||
use App\Enums\RolePermissionPrefixes;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Spatie\Permission\Models\Role as BaseRole;
|
||||
|
||||
/**
|
||||
@ -17,6 +18,8 @@ use Spatie\Permission\Models\Role as BaseRole;
|
||||
*/
|
||||
class Role extends BaseRole
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public const RESOURCE_NAME = 'role';
|
||||
|
||||
public const ROOT_ADMIN = 'Root Admin';
|
||||
|
@ -56,6 +56,8 @@
|
||||
"mockery/mockery": "^1.6.11",
|
||||
"nunomaduro/collision": "^8.6",
|
||||
"pestphp/pest": "^3.7",
|
||||
"pestphp/pest-plugin-faker": "^3.0",
|
||||
"pestphp/pest-plugin-livewire": "^3.0",
|
||||
"spatie/laravel-ignition": "^2.9"
|
||||
},
|
||||
"autoload": {
|
||||
|
135
composer.lock
generated
135
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "e78193e058fd9f763da97bbc11934c2d",
|
||||
"content-hash": "556cda6914cb34938f738f77ab4b6949",
|
||||
"packages": [
|
||||
{
|
||||
"name": "abdelhamiderrahmouni/filament-monaco-editor",
|
||||
@ -13616,6 +13616,137 @@
|
||||
],
|
||||
"time": "2025-04-16T22:59:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pestphp/pest-plugin-faker",
|
||||
"version": "v3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pestphp/pest-plugin-faker.git",
|
||||
"reference": "48343e2806cfc12a042dead90ffff4a043167e3e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pestphp/pest-plugin-faker/zipball/48343e2806cfc12a042dead90ffff4a043167e3e",
|
||||
"reference": "48343e2806cfc12a042dead90ffff4a043167e3e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"fakerphp/faker": "^1.23.1",
|
||||
"pestphp/pest": "^3.0.0",
|
||||
"php": "^8.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"pestphp/pest-dev-tools": "^3.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/Faker.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Pest\\Faker\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "The Pest Faker Plugin",
|
||||
"keywords": [
|
||||
"faker",
|
||||
"framework",
|
||||
"pest",
|
||||
"php",
|
||||
"plugin",
|
||||
"test",
|
||||
"testing",
|
||||
"unit"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/pestphp/pest-plugin-faker/tree/v3.0.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nunomaduro",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://www.patreon.com/nunomaduro",
|
||||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-08T23:56:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pestphp/pest-plugin-livewire",
|
||||
"version": "v3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pestphp/pest-plugin-livewire.git",
|
||||
"reference": "e2f2edb0a7d414d6837d87908a0e148256d3bf89"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pestphp/pest-plugin-livewire/zipball/e2f2edb0a7d414d6837d87908a0e148256d3bf89",
|
||||
"reference": "e2f2edb0a7d414d6837d87908a0e148256d3bf89",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"livewire/livewire": "^3.5.6",
|
||||
"pestphp/pest": "^3.0.0",
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"orchestra/testbench": "^9.4.0",
|
||||
"pestphp/pest-dev-tools": "^3.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/Autoload.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Pest\\Livewire\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "The Pest Livewire Plugin",
|
||||
"keywords": [
|
||||
"framework",
|
||||
"livewire",
|
||||
"pest",
|
||||
"php",
|
||||
"plugin",
|
||||
"test",
|
||||
"testing",
|
||||
"unit"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/pestphp/pest-plugin-livewire/tree/v3.0.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nunomaduro",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://www.patreon.com/nunomaduro",
|
||||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-09T00:05:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pestphp/pest-plugin-mutate",
|
||||
"version": "v3.0.5",
|
||||
@ -15775,5 +15906,5 @@
|
||||
"platform-overrides": {
|
||||
"php": "8.2"
|
||||
},
|
||||
"plugin-api-version": "2.6.0"
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
||||
|
18
database/Factories/PermissionFactory.php
Normal file
18
database/Factories/PermissionFactory.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Permission;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class PermissionFactory extends Factory
|
||||
{
|
||||
protected $model = Permission::class;
|
||||
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
|
||||
];
|
||||
}
|
||||
}
|
22
database/Factories/RoleFactory.php
Normal file
22
database/Factories/RoleFactory.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Role;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class RoleFactory extends Factory
|
||||
{
|
||||
protected $model = Role::class;
|
||||
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->faker->name(),
|
||||
'guard_name' => $this->faker->name(),
|
||||
'created_at' => Carbon::now(),
|
||||
'updated_at' => Carbon::now(),
|
||||
];
|
||||
}
|
||||
}
|
179
tests/Feature/SettingsControllerTest.php
Normal file
179
tests/Feature/SettingsControllerTest.php
Normal file
@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\ServerState;
|
||||
use App\Http\Controllers\Api\Client\Servers\SettingsController;
|
||||
use App\Models\Permission;
|
||||
use App\Repositories\Daemon\DaemonServerRepository;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
pest()->group('API');
|
||||
|
||||
covers(SettingsController::class);
|
||||
|
||||
it('server name cannot be changed', function () {
|
||||
[$user, $server] = generateTestAccount([Permission::ACTION_WEBSOCKET_CONNECT]);
|
||||
$originalName = $server->name;
|
||||
|
||||
$this->actingAs($user)
|
||||
->post("/api/client/servers/$server->uuid/settings/rename", [
|
||||
'name' => 'Test Server Name',
|
||||
])
|
||||
->assertStatus(Response::HTTP_FORBIDDEN);
|
||||
|
||||
$server = $server->refresh();
|
||||
expect()->toLogActivities(0)
|
||||
->and($server->name)->toBe($originalName);
|
||||
});
|
||||
|
||||
it('server description can be changed', function () {
|
||||
[$user, $server] = generateTestAccount([Permission::ACTION_SETTINGS_DESCRIPTION]);
|
||||
$originalDescription = $server->description;
|
||||
|
||||
$newDescription = 'Test Server Description';
|
||||
$this->actingAs($user)
|
||||
->post("/api/client/servers/$server->uuid/settings/description", [
|
||||
'description' => $newDescription,
|
||||
])
|
||||
->assertStatus(Response::HTTP_NO_CONTENT);
|
||||
|
||||
$server = $server->refresh();
|
||||
$logged = \App\Models\ActivityLog::first();
|
||||
expect()->toLogActivities(1)
|
||||
->and($logged->properties['old'])->toBe($originalDescription)
|
||||
->and($logged->properties['new'])->toBe($newDescription)
|
||||
->and($server->description)->not()->toBe($originalDescription);
|
||||
});
|
||||
|
||||
it('server description cannot be changed', function () {
|
||||
[$user, $server] = generateTestAccount([Permission::ACTION_SETTINGS_DESCRIPTION]);
|
||||
Config::set('panel.editable_server_descriptions', false);
|
||||
$originalDescription = $server->description;
|
||||
|
||||
$this->actingAs($user)
|
||||
->post("/api/client/servers/$server->uuid/settings/description", [
|
||||
'description' => 'Test Description',
|
||||
])
|
||||
->assertStatus(Response::HTTP_NO_CONTENT);
|
||||
|
||||
$server = $server->refresh();
|
||||
expect()->toLogActivities(0)
|
||||
->and($server->description)->toBe($originalDescription);
|
||||
});
|
||||
|
||||
it('server name can be changed', function () {
|
||||
[$user, $server] = generateTestAccount([Permission::ACTION_WEBSOCKET_CONNECT, Permission::ACTION_SETTINGS_RENAME]);
|
||||
$originalName = $server->name;
|
||||
|
||||
$this->actingAs($user)
|
||||
->post("/api/client/servers/$server->uuid/settings/rename", [
|
||||
'name' => 'Test Server Name',
|
||||
])
|
||||
->assertStatus(Response::HTTP_NO_CONTENT);
|
||||
|
||||
$server = $server->refresh();
|
||||
expect()->toLogActivities(1)
|
||||
->and($server->name)->not()->toBe($originalName);
|
||||
});
|
||||
|
||||
test('unauthorized user cannot change docker image in use by server', function () {
|
||||
[$user, $server] = generateTestAccount([Permission::ACTION_WEBSOCKET_CONNECT]);
|
||||
$originalImage = $server->image;
|
||||
|
||||
$this->actingAs($user)
|
||||
->put("/api/client/servers/$server->uuid/settings/docker-image", [
|
||||
'docker_image' => 'ghcr.io/pelican-dev/yolks:java_21',
|
||||
])
|
||||
->assertStatus(Response::HTTP_FORBIDDEN);
|
||||
|
||||
$server = $server->refresh();
|
||||
expect()->toLogActivities(0)
|
||||
->and($server->image)->toBe($originalImage);
|
||||
});
|
||||
|
||||
test('cannot change docker image to image not allowed by egg', function () {
|
||||
|
||||
[$user, $server] = generateTestAccount([Permission::ACTION_STARTUP_DOCKER_IMAGE]);
|
||||
$server->image = 'ghcr.io/parkervcp/yolks:java_17';
|
||||
$server->save();
|
||||
|
||||
$newImage = 'ghcr.io/parkervcp/fake:image';
|
||||
|
||||
$server = $server->refresh();
|
||||
|
||||
$this->actingAs($user)
|
||||
->putJson("/api/client/servers/$server->uuid/settings/docker-image", [
|
||||
'docker_image' => $newImage,
|
||||
])
|
||||
->assertStatus(Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
|
||||
$server->refresh();
|
||||
expect()->toLogActivities(0)
|
||||
->and($server->image)->not()->toBe($newImage);
|
||||
});
|
||||
|
||||
test('can change docker image in use by server', function () {
|
||||
[$user, $server] = generateTestAccount([Permission::ACTION_STARTUP_DOCKER_IMAGE]);
|
||||
$oldImage = 'ghcr.io/parkervcp/yolks:java_17';
|
||||
$server->image = $oldImage;
|
||||
$server->save();
|
||||
|
||||
$newImage = 'ghcr.io/parkervcp/yolks:java_21';
|
||||
|
||||
$this->actingAs($user)
|
||||
->putJson("/api/client/servers/$server->uuid/settings/docker-image", [
|
||||
'docker_image' => $newImage,
|
||||
])
|
||||
->assertStatus(Response::HTTP_NO_CONTENT);
|
||||
|
||||
$server = $server->refresh();
|
||||
|
||||
$logItem = \App\Models\ActivityLog::first();
|
||||
expect()->toLogActivities(1)
|
||||
->and($logItem->properties['old'])->toBe($oldImage)
|
||||
->and($logItem->properties['new'])->toBe($newImage)
|
||||
->and($server->image)->toBe($newImage);
|
||||
});
|
||||
|
||||
test('unable to change the docker image set by administrator', function () {
|
||||
[$user, $server] = generateTestAccount([Permission::ACTION_STARTUP_DOCKER_IMAGE]);
|
||||
$oldImage = 'ghcr.io/parkervcp/yolks:java_custom';
|
||||
$server->image = $oldImage;
|
||||
$server->save();
|
||||
|
||||
$newImage = 'ghcr.io/parkervcp/yolks:java_8';
|
||||
|
||||
$this->actingAs($user)
|
||||
->putJson("/api/client/servers/$server->uuid/settings/docker-image", [
|
||||
'docker_image' => $newImage,
|
||||
])
|
||||
->assertStatus(Response::HTTP_BAD_REQUEST);
|
||||
|
||||
$server = $server->refresh();
|
||||
|
||||
expect()->toLogActivities(0)
|
||||
->and($server->image)->toBe($oldImage);
|
||||
});
|
||||
|
||||
test('can be reinstalled', function () {
|
||||
[$user, $server] = generateTestAccount([Permission::ACTION_SETTINGS_REINSTALL]);
|
||||
expect($server->isInstalled())->toBeTrue();
|
||||
|
||||
$service = \Mockery::mock(DaemonServerRepository::class);
|
||||
$this->app->instance(DaemonServerRepository::class, $service);
|
||||
|
||||
$service->expects('setServer')
|
||||
->with(\Mockery::on(function ($value) use ($server) {
|
||||
return $value->uuid === $server->uuid;
|
||||
}))
|
||||
->andReturnSelf()
|
||||
->getMock()
|
||||
->expects('reinstall')
|
||||
->andReturnUndefined();
|
||||
|
||||
$this->actingAs($user)->postJson("/api/client/servers/$server->uuid/settings/reinstall")
|
||||
->assertStatus(Response::HTTP_ACCEPTED);
|
||||
|
||||
$server = $server->refresh();
|
||||
expect()->toLogActivities(1)
|
||||
->and($server->status)->toBe(ServerState::Installing);
|
||||
});
|
49
tests/Filament/Admin/ListEggsTest.php
Normal file
49
tests/Filament/Admin/ListEggsTest.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\RolePermissionModels;
|
||||
use App\Filament\Admin\Resources\EggResource\Pages\ListEggs;
|
||||
use App\Models\Egg;
|
||||
use App\Models\Permission;
|
||||
use App\Models\Role;
|
||||
|
||||
use function Pest\Livewire\livewire;
|
||||
|
||||
it('root admin can see all eggs', function () {
|
||||
$eggs = Egg::all();
|
||||
[$admin] = generateTestAccount([]);
|
||||
$admin = $admin->syncRoles(Role::getRootAdmin());
|
||||
|
||||
$this->actingAs($admin);
|
||||
livewire(ListEggs::class)
|
||||
->assertSuccessful()
|
||||
->assertCountTableRecords($eggs->count())
|
||||
->assertCanSeeTableRecords($eggs);
|
||||
});
|
||||
|
||||
it('non root admin cannot see any eggs', function () {
|
||||
$role = Role::factory()->create(['name' => 'Node Viewer', 'guard_name' => 'web']);
|
||||
// Node Permission is on purpose, we check the wrong permissions.
|
||||
$permission = Permission::factory()->create(['name' => RolePermissionModels::Node->viewAny(), 'guard_name' => 'web']);
|
||||
$role->permissions()->attach($permission);
|
||||
[$user] = generateTestAccount([]);
|
||||
|
||||
$this->actingAs($user);
|
||||
livewire(ListEggs::class)
|
||||
->assertForbidden();
|
||||
});
|
||||
|
||||
it('non root admin with permissions can see eggs', function () {
|
||||
$role = Role::factory()->create(['name' => 'Egg Viewer', 'guard_name' => 'web']);
|
||||
$permission = Permission::factory()->create(['name' => RolePermissionModels::Egg->viewAny(), 'guard_name' => 'web']);
|
||||
$role->permissions()->attach($permission);
|
||||
|
||||
$eggs = Egg::all();
|
||||
[$user] = generateTestAccount([]);
|
||||
$user = $user->syncRoles($role);
|
||||
|
||||
$this->actingAs($user);
|
||||
livewire(ListEggs::class)
|
||||
->assertSuccessful()
|
||||
->assertCountTableRecords($eggs->count())
|
||||
->assertCanSeeTableRecords($eggs);
|
||||
});
|
67
tests/Filament/Admin/ListNodesTest.php
Normal file
67
tests/Filament/Admin/ListNodesTest.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\RolePermissionModels;
|
||||
use App\Filament\Admin\Resources\NodeResource\Pages\ListNodes;
|
||||
use App\Models\Node;
|
||||
use App\Models\Permission;
|
||||
use App\Models\Role;
|
||||
use App\Models\Server;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Tables\Actions\CreateAction as TableCreateAction;
|
||||
|
||||
use function Pest\Livewire\livewire;
|
||||
|
||||
it('root admin can see all nodes', function () {
|
||||
[$admin] = generateTestAccount([]);
|
||||
$admin = $admin->syncRoles(Role::getRootAdmin());
|
||||
$nodes = Node::all();
|
||||
|
||||
$this->actingAs($admin);
|
||||
livewire(ListNodes::class)
|
||||
->assertSuccessful()
|
||||
->assertCountTableRecords($nodes->count())
|
||||
->assertCanSeeTableRecords($nodes);
|
||||
});
|
||||
|
||||
it('non root admin cannot see any nodes', function () {
|
||||
$role = Role::factory()->create(['name' => 'Egg Viewer', 'guard_name' => 'web']);
|
||||
// Egg Permission is on purpose, we check the wrong permissions.
|
||||
$permission = Permission::factory()->create(['name' => RolePermissionModels::Egg->viewAny(), 'guard_name' => 'web']);
|
||||
$role->permissions()->attach($permission);
|
||||
[$user] = generateTestAccount();
|
||||
|
||||
$this->actingAs($user);
|
||||
livewire(ListNodes::class)
|
||||
->assertForbidden();
|
||||
});
|
||||
|
||||
it('non root admin with permissions can see nodes', function () {
|
||||
$role = Role::factory()->create(['name' => 'Node Viewer', 'guard_name' => 'web']);
|
||||
$permission = Permission::factory()->create(['name' => RolePermissionModels::Node->viewAny(), 'guard_name' => 'web']);
|
||||
$role->permissions()->attach($permission);
|
||||
|
||||
[$user] = generateTestAccount();
|
||||
$nodes = Node::all();
|
||||
$user = $user->syncRoles($role);
|
||||
|
||||
$this->actingAs($user);
|
||||
livewire(ListNodes::class)
|
||||
->assertSuccessful()
|
||||
->assertCountTableRecords($nodes->count())
|
||||
->assertCanSeeTableRecords($nodes);
|
||||
});
|
||||
|
||||
it('displays the create button in the table instead of the header when 0 nodes', function () {
|
||||
[$admin] = generateTestAccount([]);
|
||||
$admin = $admin->syncRoles(Role::getRootAdmin());
|
||||
|
||||
// Nuke servers & nodes
|
||||
Server::truncate();
|
||||
Node::truncate();
|
||||
|
||||
$this->actingAs($admin);
|
||||
livewire(ListNodes::class)
|
||||
->assertSuccessful()
|
||||
->assertHeaderMissing(CreateAction::class)
|
||||
->assertActionExists(TableCreateAction::class);
|
||||
});
|
132
tests/Pest.php
132
tests/Pest.php
@ -24,10 +24,26 @@
|
||||
|
|
||||
*/
|
||||
|
||||
use App\Models\ActivityLog;
|
||||
use App\Models\Allocation;
|
||||
use App\Models\Egg;
|
||||
use App\Models\Node;
|
||||
use App\Models\Server;
|
||||
use App\Models\Subuser;
|
||||
use App\Models\User;
|
||||
use App\Tests\Integration\IntegrationTestCase;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
expect()->extend('toBeOne', function () {
|
||||
return $this->toBe(1);
|
||||
});
|
||||
|
||||
expect()->extend('toLogActivities', function (int $times) {
|
||||
expect(ActivityLog::count())->toBe($times);
|
||||
});
|
||||
|
||||
uses(IntegrationTestCase::class)->in('Feature', 'Filament');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Functions
|
||||
@ -43,3 +59,119 @@ function something()
|
||||
{
|
||||
// ..
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a user and a server for that user. If an array of permissions is passed it
|
||||
* is assumed that the user is actually a subuser of the server.
|
||||
*
|
||||
* @param string[] $permissions
|
||||
* @return array{\App\Models\User, \App\Models\Server}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a server model in the databases for the purpose of testing. If an attribute
|
||||
* is passed in that normally requires this function to create a model no model will be
|
||||
* created and that attribute's value will be used.
|
||||
*
|
||||
* The returned server model will have all the relationships loaded onto it.
|
||||
*/
|
||||
function createServerModel(array $attributes = []): Server
|
||||
{
|
||||
if (isset($attributes['user_id'])) {
|
||||
$attributes['owner_id'] = $attributes['user_id'];
|
||||
}
|
||||
|
||||
if (!isset($attributes['owner_id'])) {
|
||||
/** @var \App\Models\User $user */
|
||||
$user = User::factory()->create();
|
||||
$attributes['owner_id'] = $user->id;
|
||||
}
|
||||
|
||||
if (!isset($attributes['node_id'])) {
|
||||
/** @var \App\Models\Node $node */
|
||||
$node = Node::factory()->create();
|
||||
$attributes['node_id'] = $node->id;
|
||||
}
|
||||
|
||||
if (!isset($attributes['allocation_id'])) {
|
||||
/** @var \App\Models\Allocation $allocation */
|
||||
$allocation = Allocation::factory()->create(['node_id' => $attributes['node_id']]);
|
||||
$attributes['allocation_id'] = $allocation->id;
|
||||
}
|
||||
|
||||
if (empty($attributes['egg_id'])) {
|
||||
$egg = getBungeecordEgg();
|
||||
|
||||
$attributes['egg_id'] = $egg->id;
|
||||
}
|
||||
|
||||
unset($attributes['user_id']);
|
||||
|
||||
/** @var \App\Models\Server $server */
|
||||
$server = Server::factory()->create($attributes);
|
||||
|
||||
Allocation::query()->where('id', $server->allocation_id)->update(['server_id' => $server->id]);
|
||||
|
||||
return $server->fresh([
|
||||
'user', 'node', 'allocation', 'egg',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a user and a server for that user. If an array of permissions is passed it
|
||||
* is assumed that the user is actually a subuser of the server.
|
||||
*
|
||||
* @param string[] $permissions
|
||||
* @return array{\App\Models\User, \App\Models\Server}
|
||||
*/
|
||||
function generateTestAccount(array $permissions = []): array
|
||||
{
|
||||
/** @var \App\Models\User $user */
|
||||
$user = User::factory()->create();
|
||||
|
||||
if (empty($permissions)) {
|
||||
return [$user, createServerModel(['user_id' => $user->id])];
|
||||
}
|
||||
|
||||
$server = createServerModel();
|
||||
|
||||
Subuser::query()->create([
|
||||
'user_id' => $user->id,
|
||||
'server_id' => $server->id,
|
||||
'permissions' => $permissions,
|
||||
]);
|
||||
|
||||
return [$user, $server];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones a given egg allowing us to make modifications that don't affect other
|
||||
* tests that rely on the egg existing in the correct state.
|
||||
*/
|
||||
function cloneEggAndVariables(Egg $egg): Egg
|
||||
{
|
||||
$model = $egg->replicate(['id', 'uuid']);
|
||||
$model->uuid = Uuid::uuid4()->toString();
|
||||
$model->push();
|
||||
|
||||
/** @var \App\Models\Egg $model */
|
||||
$model = $model->fresh();
|
||||
|
||||
foreach ($egg->variables as $variable) {
|
||||
$variable->replicate(['id', 'egg_id'])->forceFill(['egg_id' => $model->id])->push();
|
||||
}
|
||||
|
||||
return $model->fresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Almost every test just assumes it is using BungeeCord — this is the critical
|
||||
* egg model for all tests unless specified otherwise.
|
||||
*/
|
||||
function getBungeecordEgg(): Egg
|
||||
{
|
||||
/** @var \App\Models\Egg $egg */
|
||||
$egg = Egg::query()->where('author', 'panel@example.com')->where('name', 'Bungeecord')->firstOrFail();
|
||||
|
||||
return $egg;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user