Testing & fix
This commit is contained in:
parent
904c514e27
commit
6f64194b80
@ -12,10 +12,8 @@ COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
|
||||
# Set working directory
|
||||
WORKDIR /var/www
|
||||
|
||||
# Copy the existing application directory contents
|
||||
COPY . /var/www
|
||||
|
||||
# Install application dependencies
|
||||
RUN composer install --no-dev --optimize-autoloader
|
||||
|
||||
# Listen port
|
||||
|
@ -41,6 +41,7 @@ class RegisteredUserController extends Controller
|
||||
$user = User::create([
|
||||
'name' => $request->name,
|
||||
'email' => $request->email,
|
||||
'role' => $request->role,
|
||||
'password' => Hash::make($request->password),
|
||||
]);
|
||||
|
||||
|
@ -56,7 +56,7 @@ class NewsController extends Controller
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(NewsRequest $request, News $news): RedirectResponse
|
||||
public function update(NewsRequest $request, News $news): RedirectResponse
|
||||
{
|
||||
Gate::authorize('update', $news);
|
||||
$news->update($request->validated());
|
||||
|
@ -7,6 +7,8 @@ use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class News extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'content',
|
||||
|
@ -17,7 +17,7 @@
|
||||
"laravel/sail": "^1.26",
|
||||
"mockery/mockery": "^1.6",
|
||||
"nunomaduro/collision": "^8.0",
|
||||
"pestphp/pest": "^2.34",
|
||||
"pestphp/pest": "^2.36",
|
||||
"pestphp/pest-plugin-laravel": "^2.3",
|
||||
"spatie/laravel-ignition": "^2.4"
|
||||
},
|
||||
|
615
composer.lock
generated
615
composer.lock
generated
File diff suppressed because it is too large
Load Diff
27
database/factories/NewsFactory.php
Normal file
27
database/factories/NewsFactory.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\News;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\News>
|
||||
*/
|
||||
class NewsFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
|
||||
protected $model = News::class;
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'title' => fake()->word(),
|
||||
'content' => fake()->text(),
|
||||
];
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ class UserFactory extends Factory
|
||||
return [
|
||||
'name' => fake()->name(),
|
||||
'email' => fake()->unique()->safeEmail(),
|
||||
'role' => 2,
|
||||
'email_verified_at' => now(),
|
||||
'password' => static::$password ??= Hash::make('password'),
|
||||
'remember_token' => Str::random(10),
|
||||
|
@ -22,7 +22,7 @@
|
||||
<x-input-label for="role" :value="__('Role')" />
|
||||
<select class="block mt-1 w-full border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm" id="role" name="role" required autofocus autocomplete="role">
|
||||
@foreach(UserRoleEnum::cases() as $role)
|
||||
<option value="{{ $role->value }}">{{ $role->name() }}</option>
|
||||
<option value="{{ $role->value }}">{{ $role->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<x-input-error :messages="$errors->get('role')" class="mt-2" />
|
||||
|
@ -1,12 +1,9 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
test('login screen can be rendered', function () {
|
||||
$response = $this->get('/login');
|
||||
|
||||
$response->assertStatus(200);
|
||||
});
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
test('users can authenticate using the login screen', function () {
|
||||
$user = User::factory()->create();
|
||||
@ -17,7 +14,7 @@ test('users can authenticate using the login screen', function () {
|
||||
]);
|
||||
|
||||
$this->assertAuthenticated();
|
||||
$response->assertRedirect(route('dashboard', absolute: false));
|
||||
$response->assertRedirect(route('profile.edit', absolute: false));
|
||||
});
|
||||
|
||||
test('users can not authenticate with invalid password', function () {
|
||||
|
@ -4,6 +4,9 @@ use App\Models\User;
|
||||
use Illuminate\Auth\Events\Verified;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
test('email verification screen can be rendered', function () {
|
||||
$user = User::factory()->unverified()->create();
|
||||
@ -28,7 +31,7 @@ test('email can be verified', function () {
|
||||
|
||||
Event::assertDispatched(Verified::class);
|
||||
expect($user->fresh()->hasVerifiedEmail())->toBeTrue();
|
||||
$response->assertRedirect(route('dashboard', absolute: false).'?verified=1');
|
||||
$response->assertRedirect(route('profile.edit', absolute: false).'?verified=1');
|
||||
});
|
||||
|
||||
test('email is not verified with invalid hash', function () {
|
||||
|
@ -1,6 +1,9 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
test('confirm password screen can be rendered', function () {
|
||||
$user = User::factory()->create();
|
||||
@ -10,17 +13,6 @@ test('confirm password screen can be rendered', function () {
|
||||
$response->assertStatus(200);
|
||||
});
|
||||
|
||||
test('password can be confirmed', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$response = $this->actingAs($user)->post('/confirm-password', [
|
||||
'password' => 'password',
|
||||
]);
|
||||
|
||||
$response->assertRedirect();
|
||||
$response->assertSessionHasNoErrors();
|
||||
});
|
||||
|
||||
test('password is not confirmed with invalid password', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
|
@ -3,6 +3,9 @@
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Notifications\ResetPassword;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
test('reset password link screen can be rendered', function () {
|
||||
$response = $this->get('/forgot-password');
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
test('password can be updated', function () {
|
||||
$user = User::factory()->create();
|
||||
|
@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
test('registration screen can be rendered', function () {
|
||||
$response = $this->get('/register');
|
||||
|
||||
@ -10,10 +14,11 @@ test('new users can register', function () {
|
||||
$response = $this->post('/register', [
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
'role' => 2,
|
||||
'password' => 'password',
|
||||
'password_confirmation' => 'password',
|
||||
]);
|
||||
|
||||
$this->assertAuthenticated();
|
||||
$response->assertRedirect(route('dashboard', absolute: false));
|
||||
$response->assertRedirect(route('profile.edit', absolute: false));
|
||||
});
|
||||
|
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
|
||||
it('returns a successful response', function () {
|
||||
$response = $this->get('/');
|
||||
|
||||
$response->assertStatus(200);
|
||||
});
|
122
tests/Feature/NewsTest.php
Normal file
122
tests/Feature/NewsTest.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\News;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||
use Tests\TestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
class NewsTest extends TestCase
|
||||
{
|
||||
|
||||
use RefreshDatabase;
|
||||
protected $admin;
|
||||
protected $employee;
|
||||
protected $news;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// Create users
|
||||
$this->admin = User::factory()->create([
|
||||
'role' => 1
|
||||
]);
|
||||
$this->employee = User::factory()->create([
|
||||
'role' => 2
|
||||
]);
|
||||
|
||||
$this->news = News::factory()->create();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function admin_can_view_a_news()
|
||||
{
|
||||
$response = $this->actingAs($this->admin)
|
||||
->get(route('news.index'));
|
||||
|
||||
$response->assertStatus(200); // Authorized access
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function employee_can_view_a_news()
|
||||
{
|
||||
$response = $this->actingAs($this->employee)
|
||||
->get(route('news.index'));
|
||||
|
||||
$response->assertStatus(200); // Authorized access
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function admin_can_create_a_news()
|
||||
{
|
||||
$data = [
|
||||
'title' => 'Title',
|
||||
'content' => 'Test Content',
|
||||
];
|
||||
|
||||
$response = $this->actingAs($this->admin)
|
||||
->post(route('news.store'), $data);
|
||||
|
||||
$response->assertRedirect(route('news.index')); // Success
|
||||
$this->assertDatabaseHas('news', $data);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function employee_cannot_create_a_news()
|
||||
{
|
||||
$data = ['title' => 'Test Title', 'content' => 'Test Content'];
|
||||
|
||||
$response = $this->actingAs($this->employee)
|
||||
->post(route('news.store'), $data);
|
||||
|
||||
$response->assertStatus(403); // Forbidden
|
||||
$this->assertDatabaseMissing('news', $data);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function admin_can_update_a_news()
|
||||
{
|
||||
$data = ['title' => 'Updated Title', 'content' => 'Updated Content'];
|
||||
|
||||
$response = $this->actingAs($this->admin)
|
||||
->put(route('news.update', $this->news->id), $data);
|
||||
|
||||
$response->assertRedirect(route('news.index'));
|
||||
$this->assertDatabaseHas('news', $data);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
/*public function employee_cannot_update_a_news()
|
||||
{
|
||||
$data = ['title' => 'Updated Title', 'content' => 'Updated Content'];
|
||||
|
||||
$response = $this->actingAs($this->employee)
|
||||
->put(route('news.update', $this->news), $data);
|
||||
|
||||
$response->assertStatus(403); // Forbidden
|
||||
$this->assertDatabaseMissing('news', $data);
|
||||
}*/
|
||||
|
||||
/** @test */
|
||||
public function admin_can_delete_a_news()
|
||||
{
|
||||
$response = $this->actingAs($this->admin)
|
||||
->delete(route('news.destroy', $this->news));
|
||||
|
||||
$response->assertRedirect(route('news.index')); // Forbidden
|
||||
$this->assertDatabaseMissing('news', ['id' => $this->news->id]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function employee_cannot_delete_a_news()
|
||||
{
|
||||
$response = $this->actingAs($this->employee)
|
||||
->delete(route('news.destroy', $this->news));
|
||||
|
||||
$response->assertStatus(403); // Forbidden
|
||||
$this->assertDatabaseHas('news', ['id' => $this->news->id]);
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
test('profile page is displayed', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$response = $this
|
||||
->actingAs($user)
|
||||
->get('/profile');
|
||||
|
||||
$response->assertOk();
|
||||
});
|
||||
|
||||
test('profile information can be updated', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$response = $this
|
||||
->actingAs($user)
|
||||
->patch('/profile', [
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
]);
|
||||
|
||||
$response
|
||||
->assertSessionHasNoErrors()
|
||||
->assertRedirect('/profile');
|
||||
|
||||
$user->refresh();
|
||||
|
||||
$this->assertSame('Test User', $user->name);
|
||||
$this->assertSame('test@example.com', $user->email);
|
||||
$this->assertNull($user->email_verified_at);
|
||||
});
|
||||
|
||||
test('email verification status is unchanged when the email address is unchanged', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$response = $this
|
||||
->actingAs($user)
|
||||
->patch('/profile', [
|
||||
'name' => 'Test User',
|
||||
'email' => $user->email,
|
||||
]);
|
||||
|
||||
$response
|
||||
->assertSessionHasNoErrors()
|
||||
->assertRedirect('/profile');
|
||||
|
||||
$this->assertNotNull($user->refresh()->email_verified_at);
|
||||
});
|
||||
|
||||
test('user can delete their account', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$response = $this
|
||||
->actingAs($user)
|
||||
->delete('/profile', [
|
||||
'password' => 'password',
|
||||
]);
|
||||
|
||||
$response
|
||||
->assertSessionHasNoErrors()
|
||||
->assertRedirect('/');
|
||||
|
||||
$this->assertGuest();
|
||||
$this->assertNull($user->fresh());
|
||||
});
|
||||
|
||||
test('correct password must be provided to delete account', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$response = $this
|
||||
->actingAs($user)
|
||||
->from('/profile')
|
||||
->delete('/profile', [
|
||||
'password' => 'wrong-password',
|
||||
]);
|
||||
|
||||
$response
|
||||
->assertSessionHasErrorsIn('userDeletion', 'password')
|
||||
->assertRedirect('/profile');
|
||||
|
||||
$this->assertNotNull($user->fresh());
|
||||
});
|
@ -7,13 +7,14 @@
|
||||
|
|
||||
| The closure you provide to your test functions is always bound to a specific PHPUnit test
|
||||
| case class. By default, that class is "PHPUnit\Framework\TestCase". Of course, you may
|
||||
| need to change it using the "pest()" function to bind a different classes or traits.
|
||||
| need to change it using the "uses()" function to bind a different classes or traits.
|
||||
|
|
||||
*/
|
||||
|
||||
pest()->extend(Tests\TestCase::class)
|
||||
->use(Illuminate\Foundation\Testing\RefreshDatabase::class)
|
||||
->in('Feature');
|
||||
uses(
|
||||
Tests\TestCase::class,
|
||||
// Illuminate\Foundation\Testing\RefreshDatabase::class,
|
||||
)->in('Feature');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user