test(browser): cover resource settings persistence
This commit is contained in:
parent
f09bbb4a04
commit
37eac11df3
8 changed files with 294 additions and 153 deletions
|
|
@ -31,6 +31,15 @@
|
||||||
Server::flushIdentityMap();
|
Server::flushIdentityMap();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function loginAndSkipBoarding(string $email = 'test@example.com', string $password = 'password'): mixed
|
||||||
|
{
|
||||||
|
return visit('/login')
|
||||||
|
->fill('email', $email)
|
||||||
|
->fill('password', $password)
|
||||||
|
->click('Login')
|
||||||
|
->click('Skip Setup');
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| Expectations
|
| Expectations
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Models\GithubApp;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Policies\GithubAppPolicy;
|
use App\Policies\GithubAppPolicy;
|
||||||
|
|
||||||
|
|
@ -13,12 +14,7 @@
|
||||||
it('allows any user to view system-wide github app', function () {
|
it('allows any user to view system-wide github app', function () {
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
|
|
||||||
$model = new class
|
$model = mockGithubApp(teamId: 1, isSystemWide: true);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
|
|
||||||
public $is_system_wide = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new GithubAppPolicy;
|
$policy = new GithubAppPolicy;
|
||||||
expect($policy->view($user, $model))->toBeTrue();
|
expect($policy->view($user, $model))->toBeTrue();
|
||||||
|
|
@ -32,12 +28,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
|
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
|
||||||
|
|
||||||
$model = new class
|
$model = mockGithubApp(teamId: 1, isSystemWide: false);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
|
|
||||||
public $is_system_wide = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new GithubAppPolicy;
|
$policy = new GithubAppPolicy;
|
||||||
expect($policy->view($user, $model))->toBeTrue();
|
expect($policy->view($user, $model))->toBeTrue();
|
||||||
|
|
@ -51,12 +42,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
|
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
|
||||||
|
|
||||||
$model = new class
|
$model = mockGithubApp(teamId: 1, isSystemWide: false);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
|
|
||||||
public $is_system_wide = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new GithubAppPolicy;
|
$policy = new GithubAppPolicy;
|
||||||
expect($policy->view($user, $model))->toBeFalse();
|
expect($policy->view($user, $model))->toBeFalse();
|
||||||
|
|
@ -82,12 +68,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('canAccessSystemResources')->andReturn(true);
|
$user->shouldReceive('canAccessSystemResources')->andReturn(true);
|
||||||
|
|
||||||
$model = new class
|
$model = mockGithubApp(teamId: 1, isSystemWide: true);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
|
|
||||||
public $is_system_wide = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new GithubAppPolicy;
|
$policy = new GithubAppPolicy;
|
||||||
expect($policy->update($user, $model))->toBeTrue();
|
expect($policy->update($user, $model))->toBeTrue();
|
||||||
|
|
@ -97,12 +78,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('canAccessSystemResources')->andReturn(false);
|
$user->shouldReceive('canAccessSystemResources')->andReturn(false);
|
||||||
|
|
||||||
$model = new class
|
$model = mockGithubApp(teamId: 1, isSystemWide: true);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
|
|
||||||
public $is_system_wide = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new GithubAppPolicy;
|
$policy = new GithubAppPolicy;
|
||||||
expect($policy->update($user, $model))->toBeFalse();
|
expect($policy->update($user, $model))->toBeFalse();
|
||||||
|
|
@ -112,12 +88,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
|
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
|
||||||
|
|
||||||
$model = new class
|
$model = mockGithubApp(teamId: 1, isSystemWide: false);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
|
|
||||||
public $is_system_wide = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new GithubAppPolicy;
|
$policy = new GithubAppPolicy;
|
||||||
expect($policy->update($user, $model))->toBeTrue();
|
expect($policy->update($user, $model))->toBeTrue();
|
||||||
|
|
@ -127,12 +98,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
|
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
|
||||||
|
|
||||||
$model = new class
|
$model = mockGithubApp(teamId: 1, isSystemWide: false);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
|
|
||||||
public $is_system_wide = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new GithubAppPolicy;
|
$policy = new GithubAppPolicy;
|
||||||
expect($policy->update($user, $model))->toBeFalse();
|
expect($policy->update($user, $model))->toBeFalse();
|
||||||
|
|
@ -142,12 +108,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('canAccessSystemResources')->andReturn(true);
|
$user->shouldReceive('canAccessSystemResources')->andReturn(true);
|
||||||
|
|
||||||
$model = new class
|
$model = mockGithubApp(teamId: 1, isSystemWide: true);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
|
|
||||||
public $is_system_wide = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new GithubAppPolicy;
|
$policy = new GithubAppPolicy;
|
||||||
expect($policy->delete($user, $model))->toBeTrue();
|
expect($policy->delete($user, $model))->toBeTrue();
|
||||||
|
|
@ -157,12 +118,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('canAccessSystemResources')->andReturn(false);
|
$user->shouldReceive('canAccessSystemResources')->andReturn(false);
|
||||||
|
|
||||||
$model = new class
|
$model = mockGithubApp(teamId: 1, isSystemWide: true);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
|
|
||||||
public $is_system_wide = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new GithubAppPolicy;
|
$policy = new GithubAppPolicy;
|
||||||
expect($policy->delete($user, $model))->toBeFalse();
|
expect($policy->delete($user, $model))->toBeFalse();
|
||||||
|
|
@ -172,12 +128,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
|
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
|
||||||
|
|
||||||
$model = new class
|
$model = mockGithubApp(teamId: 1, isSystemWide: false);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
|
|
||||||
public $is_system_wide = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new GithubAppPolicy;
|
$policy = new GithubAppPolicy;
|
||||||
expect($policy->delete($user, $model))->toBeTrue();
|
expect($policy->delete($user, $model))->toBeTrue();
|
||||||
|
|
@ -187,12 +138,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
|
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
|
||||||
|
|
||||||
$model = new class
|
$model = mockGithubApp(teamId: 1, isSystemWide: false);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
|
|
||||||
public $is_system_wide = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new GithubAppPolicy;
|
$policy = new GithubAppPolicy;
|
||||||
expect($policy->delete($user, $model))->toBeFalse();
|
expect($policy->delete($user, $model))->toBeFalse();
|
||||||
|
|
@ -201,12 +147,7 @@
|
||||||
it('denies restore of github app', function () {
|
it('denies restore of github app', function () {
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
|
|
||||||
$model = new class
|
$model = mockGithubApp(teamId: 1, isSystemWide: false);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
|
|
||||||
public $is_system_wide = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new GithubAppPolicy;
|
$policy = new GithubAppPolicy;
|
||||||
expect($policy->restore($user, $model))->toBeFalse();
|
expect($policy->restore($user, $model))->toBeFalse();
|
||||||
|
|
@ -215,13 +156,17 @@
|
||||||
it('denies force delete of github app', function () {
|
it('denies force delete of github app', function () {
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
|
|
||||||
$model = new class
|
$model = mockGithubApp(teamId: 1, isSystemWide: false);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
|
|
||||||
public $is_system_wide = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new GithubAppPolicy;
|
$policy = new GithubAppPolicy;
|
||||||
expect($policy->forceDelete($user, $model))->toBeFalse();
|
expect($policy->forceDelete($user, $model))->toBeFalse();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function mockGithubApp(int $teamId, bool $isSystemWide): GithubApp
|
||||||
|
{
|
||||||
|
$githubApp = Mockery::mock(GithubApp::class)->makePartial();
|
||||||
|
$githubApp->team_id = $teamId;
|
||||||
|
$githubApp->is_system_wide = $isSystemWide;
|
||||||
|
|
||||||
|
return $githubApp;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Models\SharedEnvironmentVariable;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Policies\SharedEnvironmentVariablePolicy;
|
use App\Policies\SharedEnvironmentVariablePolicy;
|
||||||
|
|
||||||
|
|
@ -18,10 +19,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
|
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
|
||||||
|
|
||||||
$model = new class
|
$model = mockSharedEnvironmentVariable(teamId: 1);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new SharedEnvironmentVariablePolicy;
|
$policy = new SharedEnvironmentVariablePolicy;
|
||||||
expect($policy->view($user, $model))->toBeTrue();
|
expect($policy->view($user, $model))->toBeTrue();
|
||||||
|
|
@ -35,10 +33,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
|
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
|
||||||
|
|
||||||
$model = new class
|
$model = mockSharedEnvironmentVariable(teamId: 2);
|
||||||
{
|
|
||||||
public $team_id = 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new SharedEnvironmentVariablePolicy;
|
$policy = new SharedEnvironmentVariablePolicy;
|
||||||
expect($policy->view($user, $model))->toBeFalse();
|
expect($policy->view($user, $model))->toBeFalse();
|
||||||
|
|
@ -64,10 +59,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
|
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
|
||||||
|
|
||||||
$model = new class
|
$model = mockSharedEnvironmentVariable(teamId: 1);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new SharedEnvironmentVariablePolicy;
|
$policy = new SharedEnvironmentVariablePolicy;
|
||||||
expect($policy->update($user, $model))->toBeTrue();
|
expect($policy->update($user, $model))->toBeTrue();
|
||||||
|
|
@ -77,10 +69,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
|
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
|
||||||
|
|
||||||
$model = new class
|
$model = mockSharedEnvironmentVariable(teamId: 1);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new SharedEnvironmentVariablePolicy;
|
$policy = new SharedEnvironmentVariablePolicy;
|
||||||
expect($policy->update($user, $model))->toBeFalse();
|
expect($policy->update($user, $model))->toBeFalse();
|
||||||
|
|
@ -90,10 +79,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
|
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
|
||||||
|
|
||||||
$model = new class
|
$model = mockSharedEnvironmentVariable(teamId: 1);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new SharedEnvironmentVariablePolicy;
|
$policy = new SharedEnvironmentVariablePolicy;
|
||||||
expect($policy->delete($user, $model))->toBeTrue();
|
expect($policy->delete($user, $model))->toBeTrue();
|
||||||
|
|
@ -103,10 +89,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
|
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
|
||||||
|
|
||||||
$model = new class
|
$model = mockSharedEnvironmentVariable(teamId: 1);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new SharedEnvironmentVariablePolicy;
|
$policy = new SharedEnvironmentVariablePolicy;
|
||||||
expect($policy->delete($user, $model))->toBeFalse();
|
expect($policy->delete($user, $model))->toBeFalse();
|
||||||
|
|
@ -115,10 +98,7 @@
|
||||||
it('denies restore of shared environment variable', function () {
|
it('denies restore of shared environment variable', function () {
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
|
|
||||||
$model = new class
|
$model = mockSharedEnvironmentVariable(teamId: 1);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new SharedEnvironmentVariablePolicy;
|
$policy = new SharedEnvironmentVariablePolicy;
|
||||||
expect($policy->restore($user, $model))->toBeFalse();
|
expect($policy->restore($user, $model))->toBeFalse();
|
||||||
|
|
@ -127,10 +107,7 @@
|
||||||
it('denies force delete of shared environment variable', function () {
|
it('denies force delete of shared environment variable', function () {
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
|
|
||||||
$model = new class
|
$model = mockSharedEnvironmentVariable(teamId: 1);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new SharedEnvironmentVariablePolicy;
|
$policy = new SharedEnvironmentVariablePolicy;
|
||||||
expect($policy->forceDelete($user, $model))->toBeFalse();
|
expect($policy->forceDelete($user, $model))->toBeFalse();
|
||||||
|
|
@ -140,10 +117,7 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
|
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
|
||||||
|
|
||||||
$model = new class
|
$model = mockSharedEnvironmentVariable(teamId: 1);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new SharedEnvironmentVariablePolicy;
|
$policy = new SharedEnvironmentVariablePolicy;
|
||||||
expect($policy->manageEnvironment($user, $model))->toBeTrue();
|
expect($policy->manageEnvironment($user, $model))->toBeTrue();
|
||||||
|
|
@ -153,11 +127,16 @@
|
||||||
$user = Mockery::mock(User::class)->makePartial();
|
$user = Mockery::mock(User::class)->makePartial();
|
||||||
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
|
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
|
||||||
|
|
||||||
$model = new class
|
$model = mockSharedEnvironmentVariable(teamId: 1);
|
||||||
{
|
|
||||||
public $team_id = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
$policy = new SharedEnvironmentVariablePolicy;
|
$policy = new SharedEnvironmentVariablePolicy;
|
||||||
expect($policy->manageEnvironment($user, $model))->toBeFalse();
|
expect($policy->manageEnvironment($user, $model))->toBeFalse();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function mockSharedEnvironmentVariable(int $teamId): SharedEnvironmentVariable
|
||||||
|
{
|
||||||
|
$sharedEnvironmentVariable = Mockery::mock(SharedEnvironmentVariable::class)->makePartial();
|
||||||
|
$sharedEnvironmentVariable->team_id = $teamId;
|
||||||
|
|
||||||
|
return $sharedEnvironmentVariable;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
uses(RefreshDatabase::class);
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
InstanceSettings::create(['id' => 0]);
|
InstanceSettings::create(['id' => 0, 'is_sponsorship_popup_enabled' => false]);
|
||||||
|
|
||||||
// Create root/owner user
|
// Create root/owner user
|
||||||
$this->user = User::factory()->create([
|
$this->user = User::factory()->create([
|
||||||
|
|
@ -96,15 +96,6 @@
|
||||||
$this->member->teams()->attach(0, ['role' => 'member']);
|
$this->member->teams()->attach(0, ['role' => 'member']);
|
||||||
});
|
});
|
||||||
|
|
||||||
function loginAndSkipOnboarding(): mixed
|
|
||||||
{
|
|
||||||
return visit('/login')
|
|
||||||
->fill('email', 'test@example.com')
|
|
||||||
->fill('password', 'password')
|
|
||||||
->click('Login')
|
|
||||||
->click('Skip Setup');
|
|
||||||
}
|
|
||||||
|
|
||||||
function loginAsMember(): mixed
|
function loginAsMember(): mixed
|
||||||
{
|
{
|
||||||
return visit('/login')
|
return visit('/login')
|
||||||
|
|
@ -121,7 +112,7 @@ function loginAsMember(): mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows dashboard after successful login and onboarding skip', function () {
|
it('shows dashboard after successful login and onboarding skip', function () {
|
||||||
$page = loginAndSkipOnboarding();
|
$page = loginAndSkipBoarding();
|
||||||
|
|
||||||
$page->assertSee('Dashboard')
|
$page->assertSee('Dashboard')
|
||||||
->assertSee('Your self-hosted infrastructure')
|
->assertSee('Your self-hosted infrastructure')
|
||||||
|
|
@ -129,7 +120,7 @@ function loginAsMember(): mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
it('displays all projects on dashboard', function () {
|
it('displays all projects on dashboard', function () {
|
||||||
$page = loginAndSkipOnboarding();
|
$page = loginAndSkipBoarding();
|
||||||
|
|
||||||
$page->assertSee('Projects')
|
$page->assertSee('Projects')
|
||||||
->assertSee('My first project')
|
->assertSee('My first project')
|
||||||
|
|
@ -140,7 +131,7 @@ function loginAsMember(): mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
it('displays all servers on dashboard', function () {
|
it('displays all servers on dashboard', function () {
|
||||||
$page = loginAndSkipOnboarding();
|
$page = loginAndSkipBoarding();
|
||||||
|
|
||||||
$page->assertSee('Servers')
|
$page->assertSee('Servers')
|
||||||
->assertSee('localhost')
|
->assertSee('localhost')
|
||||||
|
|
@ -151,7 +142,7 @@ function loginAsMember(): mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows authenticated users to access team settings', function () {
|
it('allows authenticated users to access team settings', function () {
|
||||||
loginAndSkipOnboarding();
|
loginAndSkipBoarding();
|
||||||
|
|
||||||
$page = visit('/team');
|
$page = visit('/team');
|
||||||
|
|
||||||
|
|
@ -161,7 +152,7 @@ function loginAsMember(): mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows danger zone to team owner', function () {
|
it('shows danger zone to team owner', function () {
|
||||||
loginAndSkipOnboarding();
|
loginAndSkipBoarding();
|
||||||
|
|
||||||
$page = visit('/team');
|
$page = visit('/team');
|
||||||
|
|
||||||
|
|
@ -194,7 +185,7 @@ function loginAsMember(): mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
it('authenticated user can navigate to server details', function () {
|
it('authenticated user can navigate to server details', function () {
|
||||||
loginAndSkipOnboarding();
|
loginAndSkipBoarding();
|
||||||
|
|
||||||
// Navigate to server show page using UUID
|
// Navigate to server show page using UUID
|
||||||
$server = Server::first();
|
$server = Server::first();
|
||||||
|
|
@ -206,7 +197,7 @@ function loginAsMember(): mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
it('authenticated user can navigate to project details', function () {
|
it('authenticated user can navigate to project details', function () {
|
||||||
loginAndSkipOnboarding();
|
loginAndSkipBoarding();
|
||||||
|
|
||||||
// Navigate to project show page using UUID
|
// Navigate to project show page using UUID
|
||||||
$project = Project::first();
|
$project = Project::first();
|
||||||
|
|
@ -225,7 +216,7 @@ function loginAsMember(): mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
it('authenticated user can access team members page', function () {
|
it('authenticated user can access team members page', function () {
|
||||||
loginAndSkipOnboarding();
|
loginAndSkipBoarding();
|
||||||
|
|
||||||
$page = visit('/team/members');
|
$page = visit('/team/members');
|
||||||
|
|
||||||
|
|
@ -300,7 +291,7 @@ function loginAsMember(): mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
it('owner sees terminal and security links on server page', function () {
|
it('owner sees terminal and security links on server page', function () {
|
||||||
loginAndSkipOnboarding();
|
loginAndSkipBoarding();
|
||||||
|
|
||||||
$server = Server::first();
|
$server = Server::first();
|
||||||
$page = visit("/server/{$server->uuid}");
|
$page = visit("/server/{$server->uuid}");
|
||||||
|
|
@ -341,7 +332,7 @@ function loginAsMember(): mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
it('owner sees add environment and settings on project page', function () {
|
it('owner sees add environment and settings on project page', function () {
|
||||||
loginAndSkipOnboarding();
|
loginAndSkipBoarding();
|
||||||
|
|
||||||
$project = Project::where('uuid', 'project-1')->first();
|
$project = Project::where('uuid', 'project-1')->first();
|
||||||
$page = visit("/project/{$project->uuid}");
|
$page = visit("/project/{$project->uuid}");
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
uses(RefreshDatabase::class);
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
InstanceSettings::create(['id' => 0]);
|
InstanceSettings::create(['id' => 0, 'is_sponsorship_popup_enabled' => false]);
|
||||||
|
|
||||||
$this->user = User::factory()->create([
|
$this->user = User::factory()->create([
|
||||||
'id' => 0,
|
'id' => 0,
|
||||||
|
|
@ -99,15 +99,6 @@
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
function loginAndSkipOnboarding(): mixed
|
|
||||||
{
|
|
||||||
return visit('/login')
|
|
||||||
->fill('email', 'test@example.com')
|
|
||||||
->fill('password', 'password')
|
|
||||||
->click('Login')
|
|
||||||
->click('Skip Setup');
|
|
||||||
}
|
|
||||||
|
|
||||||
it('redirects to login when not authenticated', function () {
|
it('redirects to login when not authenticated', function () {
|
||||||
$page = visit('/');
|
$page = visit('/');
|
||||||
|
|
||||||
|
|
@ -128,7 +119,7 @@ function loginAndSkipOnboarding(): mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows dashboard after skipping onboarding', function () {
|
it('shows dashboard after skipping onboarding', function () {
|
||||||
$page = loginAndSkipOnboarding();
|
$page = loginAndSkipBoarding();
|
||||||
|
|
||||||
$page->assertSee('Dashboard')
|
$page->assertSee('Dashboard')
|
||||||
->assertSee('Your self-hosted infrastructure.')
|
->assertSee('Your self-hosted infrastructure.')
|
||||||
|
|
@ -136,7 +127,7 @@ function loginAndSkipOnboarding(): mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows all projects on dashboard', function () {
|
it('shows all projects on dashboard', function () {
|
||||||
$page = loginAndSkipOnboarding();
|
$page = loginAndSkipBoarding();
|
||||||
|
|
||||||
$page->assertSee('Projects')
|
$page->assertSee('Projects')
|
||||||
->assertSee('My first project')
|
->assertSee('My first project')
|
||||||
|
|
@ -149,7 +140,7 @@ function loginAndSkipOnboarding(): mixed
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows servers on dashboard', function () {
|
it('shows servers on dashboard', function () {
|
||||||
$page = loginAndSkipOnboarding();
|
$page = loginAndSkipBoarding();
|
||||||
|
|
||||||
$page->assertSee('Servers')
|
$page->assertSee('Servers')
|
||||||
->assertSee('localhost')
|
->assertSee('localhost')
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
uses(RefreshDatabase::class);
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
InstanceSettings::create(['id' => 0]);
|
InstanceSettings::create(['id' => 0, 'is_sponsorship_popup_enabled' => false]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows registration page when no users exist', function () {
|
it('shows registration page when no users exist', function () {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
uses(RefreshDatabase::class);
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
InstanceSettings::create(['id' => 0]);
|
InstanceSettings::create(['id' => 0, 'is_sponsorship_popup_enabled' => false]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows registration page when no users exist', function () {
|
it('shows registration page when no users exist', function () {
|
||||||
|
|
|
||||||
226
tests/v4/Browser/ResourceSettingsPersistenceTest.php
Normal file
226
tests/v4/Browser/ResourceSettingsPersistenceTest.php
Normal file
|
|
@ -0,0 +1,226 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\ProxyStatus;
|
||||||
|
use App\Enums\ProxyTypes;
|
||||||
|
use App\Models\Application;
|
||||||
|
use App\Models\InstanceSettings;
|
||||||
|
use App\Models\PrivateKey;
|
||||||
|
use App\Models\Project;
|
||||||
|
use App\Models\Server;
|
||||||
|
use App\Models\StandaloneDocker;
|
||||||
|
use App\Models\StandalonePostgresql;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Visus\Cuid2\Cuid2;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
InstanceSettings::create(['id' => 0, 'is_sponsorship_popup_enabled' => false]);
|
||||||
|
|
||||||
|
$this->user = User::factory()->create([
|
||||||
|
'id' => 0,
|
||||||
|
'name' => 'Root User',
|
||||||
|
'email' => 'test@example.com',
|
||||||
|
'password' => Hash::make('password'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
PrivateKey::create([
|
||||||
|
'id' => 1,
|
||||||
|
'uuid' => 'ssh-test',
|
||||||
|
'team_id' => 0,
|
||||||
|
'name' => 'Test Key',
|
||||||
|
'description' => 'Test SSH key',
|
||||||
|
'private_key' => '-----BEGIN OPENSSH PRIVATE KEY-----
|
||||||
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||||
|
QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk
|
||||||
|
hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA
|
||||||
|
AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV
|
||||||
|
uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
||||||
|
-----END OPENSSH PRIVATE KEY-----',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->server = Server::create([
|
||||||
|
'id' => 0,
|
||||||
|
'uuid' => 'localhost',
|
||||||
|
'name' => 'localhost',
|
||||||
|
'description' => 'Test docker container in development',
|
||||||
|
'ip' => 'coolify-testing-host',
|
||||||
|
'team_id' => 0,
|
||||||
|
'private_key_id' => 1,
|
||||||
|
'proxy' => [
|
||||||
|
'type' => ProxyTypes::TRAEFIK->value,
|
||||||
|
'status' => ProxyStatus::EXITED->value,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->project = Project::create([
|
||||||
|
'uuid' => 'project-resource-persistence',
|
||||||
|
'name' => 'Resource Persistence',
|
||||||
|
'description' => 'Browser persistence tests',
|
||||||
|
'team_id' => 0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->environment = $this->project->environments()->first();
|
||||||
|
|
||||||
|
StandaloneDocker::withoutEvents(function () {
|
||||||
|
$this->destination = StandaloneDocker::firstOrCreate(
|
||||||
|
['server_id' => $this->server->id, 'network' => 'coolify'],
|
||||||
|
['uuid' => 'docker-destination-1', 'name' => 'docker-destination-1']
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->application = Application::factory()->create([
|
||||||
|
'uuid' => 'app-resource-persistence',
|
||||||
|
'name' => 'App Before Browser Save',
|
||||||
|
'git_repository' => 'https://github.com/coollabsio/coolify.git',
|
||||||
|
'git_branch' => 'main',
|
||||||
|
'build_pack' => 'nixpacks',
|
||||||
|
'ports_exposes' => '3000',
|
||||||
|
'environment_id' => $this->environment->id,
|
||||||
|
'destination_id' => $this->destination->id,
|
||||||
|
'destination_type' => $this->destination->getMorphClass(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->database = StandalonePostgresql::create([
|
||||||
|
'uuid' => 'db-resource-persistence',
|
||||||
|
'name' => 'Database Before Browser Save',
|
||||||
|
'description' => 'Initial database description',
|
||||||
|
'postgres_user' => 'postgres',
|
||||||
|
'postgres_password' => 'postgres-password',
|
||||||
|
'postgres_db' => 'postgres',
|
||||||
|
'image' => 'postgres:15-alpine',
|
||||||
|
'status' => 'exited',
|
||||||
|
'environment_id' => $this->environment->id,
|
||||||
|
'destination_id' => $this->destination->id,
|
||||||
|
'destination_type' => $this->destination->getMorphClass(),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('saves application name and enables static site with nginx config', function () {
|
||||||
|
loginAndSkipBoarding();
|
||||||
|
|
||||||
|
$updatedName = 'App Saved '.(string) new Cuid2;
|
||||||
|
$applicationRoute = "/project/{$this->project->uuid}/environment/{$this->environment->uuid}/application/{$this->application->uuid}";
|
||||||
|
|
||||||
|
$page = visit($applicationRoute);
|
||||||
|
|
||||||
|
dismissNotificationPrompt($page);
|
||||||
|
$page->screenshot();
|
||||||
|
|
||||||
|
$page->assertSee('General')
|
||||||
|
->assertDontSee('Custom Nginx Configuration')
|
||||||
|
->fill('name', $updatedName)
|
||||||
|
->fill('customDockerRunOptions', '--read-only');
|
||||||
|
|
||||||
|
submitResourceForm($page);
|
||||||
|
dismissNotificationPrompt($page);
|
||||||
|
toggleCheckboxByWireModel($page, 'isStatic');
|
||||||
|
$page->screenshot();
|
||||||
|
|
||||||
|
$page->assertSee('Custom Nginx Configuration')
|
||||||
|
->assertSee('Is it a SPA (Single Page Application)?')
|
||||||
|
->assertValue('name', $updatedName);
|
||||||
|
|
||||||
|
$this->application->refresh();
|
||||||
|
expect($this->application->name)->toBe($updatedName)
|
||||||
|
->and($this->application->custom_docker_run_options)->toBe('--read-only')
|
||||||
|
->and($this->application->settings->is_static)->toBeTrue();
|
||||||
|
|
||||||
|
$reloadedPage = visit($applicationRoute);
|
||||||
|
dismissNotificationPrompt($reloadedPage);
|
||||||
|
$reloadedPage->screenshot();
|
||||||
|
|
||||||
|
$reloadedPage->assertValue('name', $updatedName)
|
||||||
|
->assertSee('Custom Nginx Configuration')
|
||||||
|
->assertSee('Is it a SPA (Single Page Application)?');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('saves database name and enables ssl with mode selector', function () {
|
||||||
|
loginAndSkipBoarding();
|
||||||
|
|
||||||
|
$updatedDatabaseName = 'Database Saved '.(string) new Cuid2;
|
||||||
|
$databaseRoute = "/project/{$this->project->uuid}/environment/{$this->environment->uuid}/database/{$this->database->uuid}";
|
||||||
|
|
||||||
|
$page = visit($databaseRoute);
|
||||||
|
|
||||||
|
dismissNotificationPrompt($page);
|
||||||
|
$page->screenshot();
|
||||||
|
|
||||||
|
$page->assertSee('General')
|
||||||
|
->assertDontSee('SSL Mode')
|
||||||
|
->fill('name', $updatedDatabaseName)
|
||||||
|
->fill('description', 'Updated by browser test');
|
||||||
|
|
||||||
|
submitResourceForm($page);
|
||||||
|
dismissNotificationPrompt($page);
|
||||||
|
|
||||||
|
toggleCheckboxByWireModel($page, 'enableSsl');
|
||||||
|
|
||||||
|
$page->assertSee('SSL Mode')
|
||||||
|
->assertValue('name', $updatedDatabaseName);
|
||||||
|
$page->screenshot();
|
||||||
|
|
||||||
|
$this->database->refresh();
|
||||||
|
expect($this->database->name)->toBe($updatedDatabaseName)
|
||||||
|
->and($this->database->description)->toBe('Updated by browser test')
|
||||||
|
->and($this->database->enable_ssl)->toBeTruthy();
|
||||||
|
|
||||||
|
$reloadedPage = visit($databaseRoute);
|
||||||
|
dismissNotificationPrompt($reloadedPage);
|
||||||
|
$reloadedPage->screenshot();
|
||||||
|
|
||||||
|
$reloadedPage->assertValue('name', $updatedDatabaseName)
|
||||||
|
->assertSee('SSL Mode');
|
||||||
|
});
|
||||||
|
|
||||||
|
function dismissNotificationPrompt($page): void
|
||||||
|
{
|
||||||
|
$page->script(<<<'JS'
|
||||||
|
const closeButtonTexts = ['Accept and Close', 'Slice', 'Maybe next time'];
|
||||||
|
for (const text of closeButtonTexts) {
|
||||||
|
const closeButton = Array.from(document.querySelectorAll('button, a'))
|
||||||
|
.find((button) => button.textContent.includes(text));
|
||||||
|
|
||||||
|
if (! closeButton) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modal =
|
||||||
|
closeButton.closest('.fixed') ??
|
||||||
|
closeButton.closest('[role="dialog"]') ??
|
||||||
|
closeButton.closest('div');
|
||||||
|
|
||||||
|
if (modal) {
|
||||||
|
modal.remove();
|
||||||
|
} else {
|
||||||
|
closeButton.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JS);
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitResourceForm($page): void
|
||||||
|
{
|
||||||
|
$page->script("
|
||||||
|
const form = document.querySelector('form[wire\\\\:submit=\"submit\"]');
|
||||||
|
if (form) {
|
||||||
|
form.requestSubmit();
|
||||||
|
}
|
||||||
|
");
|
||||||
|
$page->wait(0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleCheckboxByWireModel($page, string $wireModel): void
|
||||||
|
{
|
||||||
|
$page->script("
|
||||||
|
const checkbox = document.querySelector(
|
||||||
|
'input[wire\\\\:model=\"{$wireModel}\"], input[wire\\\\:model\\\\.live=\"{$wireModel}\"]'
|
||||||
|
);
|
||||||
|
if (checkbox) {
|
||||||
|
checkbox.click();
|
||||||
|
}
|
||||||
|
");
|
||||||
|
$page->wait(0.3);
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue