- Introduced `giveSupplierPermissions` function to streamline user permission setup for supplier tests. - Updated all supplier-related tests to utilize the new permission setup function. - Enhanced phone number validation tests to accept various formats and special characters. - Removed redundant tests related to unsupported phone number formats. - Consolidated tests for supplier creation and updates to improve readability and maintainability.
1715 lines
51 KiB
PHP
1715 lines
51 KiB
PHP
<?php
|
|
|
|
use App\Models\Category;
|
|
use App\Models\Product;
|
|
use App\Models\User;
|
|
use Database\Seeders\RolePermissionSeeder;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Str;
|
|
use Inertia\Testing\AssertableInertia as Assert;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
function giveCategoryPermissions(): User
|
|
{
|
|
$seeder = new RolePermissionSeeder;
|
|
$seeder->run();
|
|
|
|
$user = User::factory()->create();
|
|
$user->givePermissionTo([
|
|
'categories.view',
|
|
'categories.create',
|
|
'categories.update',
|
|
'categories.delete',
|
|
]);
|
|
|
|
return $user;
|
|
}
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| AUTHENTICATION
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('guests are redirected to the login page', function () {
|
|
$response = $this->get(route('admin.master.categories.index'));
|
|
$response->assertRedirect(route('login'));
|
|
});
|
|
|
|
test('authenticated users can visit the category index page', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->get(route('admin.master.categories.index'));
|
|
$response->assertOk();
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| INDEX PAGE
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('category index page displays categories', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
Category::factory()->count(3)->create();
|
|
|
|
$response = $this->get(route('admin.master.categories.index'));
|
|
$response->assertOk();
|
|
$response->assertInertia(fn (Assert $page) => $page
|
|
->component('admin/master/category/index')
|
|
->has('categories.data', 3)
|
|
->where('categories.total', 3)
|
|
->where('categories.current_page', 1)
|
|
->where('categories.per_page', 25)
|
|
);
|
|
});
|
|
|
|
test('index page works with zero categories', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->get(route('admin.master.categories.index'));
|
|
$response->assertOk();
|
|
$response->assertInertia(fn (Assert $page) => $page
|
|
->component('admin/master/category/index')
|
|
->has('categories.data', 0)
|
|
->where('categories.total', 0)
|
|
->where('categories.current_page', 1)
|
|
->where('categories.per_page', 25)
|
|
);
|
|
});
|
|
|
|
test('index page does not display soft-deleted categories', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
Category::factory()->create(['name' => 'Active Category']);
|
|
Category::factory()->create(['name' => 'Deleted Category'])->delete();
|
|
|
|
$response = $this->get(route('admin.master.categories.index'));
|
|
$response->assertOk();
|
|
$response->assertInertia(fn (Assert $page) => $page
|
|
->component('admin/master/category/index')
|
|
->has('categories.data', 1)
|
|
->where('categories.total', 1)
|
|
->where('categories.current_page', 1)
|
|
->where('categories.per_page', 25)
|
|
->where('categories.data.0.name', 'Active Category')
|
|
);
|
|
});
|
|
|
|
test('index page displays correct count after delete', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
Category::factory()->count(5)->create();
|
|
$category = Category::first();
|
|
|
|
$this->delete(route('admin.master.categories.destroy', $category));
|
|
|
|
$response = $this->get(route('admin.master.categories.index'));
|
|
$response->assertOk();
|
|
$response->assertInertia(fn (Assert $page) => $page
|
|
->component('admin/master/category/index')
|
|
->has('categories.data', 4)
|
|
->where('categories.total', 4)
|
|
->where('categories.current_page', 1)
|
|
->where('categories.per_page', 25)
|
|
);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| CREATE / STORE
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('category can be created', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Kategori Test',
|
|
]);
|
|
|
|
$response
|
|
->assertSessionHasNoErrors()
|
|
->assertRedirect();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Kategori Test',
|
|
'slug' => 'kategori-test',
|
|
]);
|
|
});
|
|
|
|
test('category slug is automatically generated from name', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Kategori Otomatis',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Kategori Otomatis',
|
|
'slug' => 'kategori-otomatis',
|
|
]);
|
|
});
|
|
|
|
test('category name is required', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => '',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('category name must be string', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 12345,
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('category name must not exceed 50 characters', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => str_repeat('a', 51),
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('category name exactly 50 characters passes validation', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => str_repeat('a', 50),
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
});
|
|
|
|
test('category name exactly 1 character passes validation', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 'A',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'A',
|
|
'slug' => 'a',
|
|
]);
|
|
});
|
|
|
|
test('category name must be unique', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
Category::factory()->create(['name' => 'Existing Category']);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Existing Category',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('category name uniqueness is case sensitive', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
Category::factory()->create(['name' => 'Makanan']);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Makanan',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('category name with only whitespace is rejected', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => ' ',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('category name with special characters is accepted', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Makanan & Minuman!',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Makanan & Minuman!',
|
|
'slug' => 'makanan-minuman',
|
|
]);
|
|
});
|
|
|
|
test('category name with HTML tags is accepted as plain text', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => '<script>alert("xss")</script>',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => '<script>alert("xss")</script>',
|
|
]);
|
|
});
|
|
|
|
test('category name with numbers is accepted', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Kategori 123',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Kategori 123',
|
|
'slug' => 'kategori-123',
|
|
]);
|
|
});
|
|
|
|
test('category name with only numbers is accepted', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => '12345',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => '12345',
|
|
'slug' => '12345',
|
|
]);
|
|
});
|
|
|
|
test('category name with only punctuation is accepted', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => '---',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
});
|
|
|
|
test('category name with parentheses and brackets is accepted', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Kategori (A) [VIP]',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Kategori (A) [VIP]',
|
|
'slug' => 'kategori-a-vip',
|
|
]);
|
|
});
|
|
|
|
test('category name with unicode characters is accepted', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Kategori Nono',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Kategori Nono',
|
|
]);
|
|
});
|
|
|
|
test('category name with mixed case is stored as entered', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 'makanAN MinUMAN',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'makanAN MinUMAN',
|
|
'slug' => 'makanan-minuman',
|
|
]);
|
|
});
|
|
|
|
test('category name with multiple spaces generates correct slug', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Kategori dengan spasi banyak',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Kategori dengan spasi banyak',
|
|
'slug' => 'kategori-dengan-spasi-banyak',
|
|
]);
|
|
});
|
|
|
|
test('category name with leading and trailing spaces is accepted', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => ' Kategori Spasi ',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
});
|
|
|
|
test('category name with newline characters is accepted', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => "Kategori\nBaru",
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
});
|
|
|
|
test('category can be created with name at exact DB column limit (50 chars)', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$name = str_repeat('a', 50);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => $name,
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => $name,
|
|
]);
|
|
});
|
|
|
|
test('store flashes success toast via Inertia', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Kategori Toast',
|
|
]);
|
|
|
|
$response->assertRedirect();
|
|
});
|
|
|
|
test('store creates new category in database', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Database Check',
|
|
]);
|
|
|
|
$this->assertDatabaseCount('categories', 1);
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Database Check',
|
|
'slug' => 'database-check',
|
|
]);
|
|
});
|
|
|
|
test('multiple categories can be created sequentially', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'Kategori 1']);
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'Kategori 2']);
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'Kategori 3']);
|
|
|
|
$this->assertDatabaseCount('categories', 3);
|
|
|
|
$this->assertDatabaseHas('categories', ['name' => 'Kategori 1', 'slug' => 'kategori-1']);
|
|
$this->assertDatabaseHas('categories', ['name' => 'Kategori 2', 'slug' => 'kategori-2']);
|
|
$this->assertDatabaseHas('categories', ['name' => 'Kategori 3', 'slug' => 'kategori-3']);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| UPDATE / PUT
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('category can be updated', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Kategori Updated',
|
|
]);
|
|
|
|
$response
|
|
->assertSessionHasNoErrors()
|
|
->assertRedirect();
|
|
|
|
$category->refresh();
|
|
expect($category->name)->toBe('Kategori Updated');
|
|
expect($category->slug)->toBe('kategori-updated');
|
|
});
|
|
|
|
test('category name can be updated to itself', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create(['name' => 'My Category']);
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'My Category',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
});
|
|
|
|
test('category update name must be unique excluding itself', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create(['name' => 'First']);
|
|
Category::factory()->create(['name' => 'Second']);
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Second',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('category update name is required', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), [
|
|
'name' => '',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('category update name must not exceed 50 characters', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), [
|
|
'name' => str_repeat('a', 51),
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('category update with special characters generates correct slug', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create(['name' => 'Old Name']);
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'New Name (Updated) & More!',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$category->refresh();
|
|
expect($category->slug)->toBe('new-name-updated-more');
|
|
});
|
|
|
|
test('category update changes the slug to match new name', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create(['name' => 'Original', 'slug' => 'original']);
|
|
|
|
$this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Modified',
|
|
]);
|
|
|
|
$category->refresh();
|
|
expect($category->slug)->toBe('modified');
|
|
});
|
|
|
|
test('category can be updated multiple times', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create(['name' => 'Version 1']);
|
|
|
|
$this->put(route('admin.master.categories.update', $category), ['name' => 'Version 2']);
|
|
$category->refresh();
|
|
expect($category->name)->toBe('Version 2');
|
|
|
|
$this->put(route('admin.master.categories.update', $category), ['name' => 'Version 3']);
|
|
$category->refresh();
|
|
expect($category->name)->toBe('Version 3');
|
|
});
|
|
|
|
test('update flashes success toast via Inertia', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Updated Name',
|
|
]);
|
|
|
|
$response->assertRedirect();
|
|
});
|
|
|
|
test('category update with only whitespace is rejected', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), [
|
|
'name' => ' ',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('category can be updated with unicode characters', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create(['name' => 'Original']);
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Kategori Nono',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$category->refresh();
|
|
expect($category->name)->toBe('Kategori Nono');
|
|
});
|
|
|
|
test('updating non-existent category returns 404', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->put(route('admin.master.categories.update', 999999), [
|
|
'name' => 'Ghost Category',
|
|
]);
|
|
|
|
$response->assertStatus(404);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| DELETE / DESTROY
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('category can be deleted', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$response = $this->delete(route('admin.master.categories.destroy', $category));
|
|
|
|
$response
|
|
->assertSessionHasNoErrors()
|
|
->assertRedirect();
|
|
|
|
$this->assertSoftDeleted('categories', ['id' => $category->id]);
|
|
});
|
|
|
|
test('category is soft-deleted not permanently removed', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$this->delete(route('admin.master.categories.destroy', $category));
|
|
|
|
$this->assertDatabaseHas('categories', ['id' => $category->id]);
|
|
$this->assertSoftDeleted('categories', ['id' => $category->id]);
|
|
});
|
|
|
|
test('soft-deleted category still exists in database', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$this->delete(route('admin.master.categories.destroy', $category));
|
|
|
|
$this->assertDatabaseHas('categories', ['id' => $category->id]);
|
|
});
|
|
|
|
test('soft-deleted category has deleted_at timestamp', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$this->delete(route('admin.master.categories.destroy', $category));
|
|
|
|
$category->refresh();
|
|
expect($category->deleted_at)->not->toBeNull();
|
|
});
|
|
|
|
test('deleted category is excluded from getAll query', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
Category::factory()->create(['name' => 'Active']);
|
|
$deleted = Category::factory()->create(['name' => 'Deleted']);
|
|
$deleted->delete();
|
|
|
|
$response = $this->get(route('admin.master.categories.index'));
|
|
$response->assertOk();
|
|
$response->assertInertia(fn (Assert $page) => $page
|
|
->component('admin/master/category/index')
|
|
->has('categories.data', 1)
|
|
->where('categories.total', 1)
|
|
->where('categories.current_page', 1)
|
|
->where('categories.per_page', 25)
|
|
->where('categories.data.0.name', 'Active')
|
|
);
|
|
});
|
|
|
|
test('delete flashes success toast via Inertia', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$response = $this->delete(route('admin.master.categories.destroy', $category));
|
|
|
|
$response->assertRedirect();
|
|
});
|
|
|
|
test('multiple categories can be deleted one by one', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$categories = Category::factory()->count(3)->create();
|
|
|
|
$this->delete(route('admin.master.categories.destroy', $categories[0]));
|
|
$this->delete(route('admin.master.categories.destroy', $categories[1]));
|
|
|
|
$this->assertSoftDeleted('categories', ['id' => $categories[0]->id]);
|
|
$this->assertSoftDeleted('categories', ['id' => $categories[1]->id]);
|
|
$this->assertDatabaseHas('categories', ['id' => $categories[2]->id, 'deleted_at' => null]);
|
|
});
|
|
|
|
test('updating soft-deleted category via route returns 404', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
$category->delete();
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Should Not Work',
|
|
]);
|
|
|
|
$response->assertStatus(404);
|
|
});
|
|
|
|
test('deleting soft-deleted category via route returns 404', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
$category->delete();
|
|
|
|
$response = $this->delete(route('admin.master.categories.destroy', $category));
|
|
|
|
$response->assertStatus(404);
|
|
});
|
|
|
|
test('deleting non-existent category returns 404', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->delete(route('admin.master.categories.destroy', 999999));
|
|
|
|
$response->assertStatus(404);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| CATEGORY - PRODUCT RELATIONSHIP
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('category with products can be deleted without deleting products', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
$product = Product::factory()->create();
|
|
DB::table('product_categories')->insert([
|
|
'product_id' => $product->id,
|
|
'category_id' => $category->id,
|
|
]);
|
|
|
|
$this->delete(route('admin.master.categories.destroy', $category));
|
|
|
|
$this->assertSoftDeleted('categories', ['id' => $category->id]);
|
|
$this->assertDatabaseHas('products', ['id' => $product->id, 'deleted_at' => null]);
|
|
});
|
|
|
|
test('category-product pivot record remains after soft delete', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
$product = Product::factory()->create();
|
|
DB::table('product_categories')->insert([
|
|
'product_id' => $product->id,
|
|
'category_id' => $category->id,
|
|
]);
|
|
|
|
$this->assertDatabaseHas('product_categories', [
|
|
'category_id' => $category->id,
|
|
'product_id' => $product->id,
|
|
]);
|
|
|
|
$this->delete(route('admin.master.categories.destroy', $category));
|
|
|
|
// Soft delete doesn't trigger cascade delete, so pivot record remains
|
|
$this->assertDatabaseHas('product_categories', [
|
|
'category_id' => $category->id,
|
|
'product_id' => $product->id,
|
|
]);
|
|
});
|
|
|
|
test('index page works correctly with categories that have products', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
$products = Product::factory()->count(3)->create();
|
|
foreach ($products as $product) {
|
|
DB::table('product_categories')->insert([
|
|
'product_id' => $product->id,
|
|
'category_id' => $category->id,
|
|
]);
|
|
}
|
|
|
|
$response = $this->get(route('admin.master.categories.index'));
|
|
$response->assertOk();
|
|
$response->assertInertia(fn (Assert $page) => $page
|
|
->component('admin/master/category/index')
|
|
->has('categories.data', 1)
|
|
->where('categories.total', 1)
|
|
->where('categories.current_page', 1)
|
|
->where('categories.per_page', 25)
|
|
);
|
|
});
|
|
|
|
test('category with many products can be deleted', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
$products = Product::factory()->count(10)->create();
|
|
foreach ($products as $product) {
|
|
DB::table('product_categories')->insert([
|
|
'product_id' => $product->id,
|
|
'category_id' => $category->id,
|
|
]);
|
|
}
|
|
|
|
$this->delete(route('admin.master.categories.destroy', $category));
|
|
|
|
$this->assertSoftDeleted('categories', ['id' => $category->id]);
|
|
$this->assertDatabaseCount('products', 10);
|
|
});
|
|
|
|
test('deleting category does not affect other categories products belong to', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category1 = Category::factory()->create();
|
|
$category2 = Category::factory()->create();
|
|
$product = Product::factory()->create();
|
|
DB::table('product_categories')->insert([
|
|
['product_id' => $product->id, 'category_id' => $category1->id],
|
|
['product_id' => $product->id, 'category_id' => $category2->id],
|
|
]);
|
|
|
|
$this->delete(route('admin.master.categories.destroy', $category1));
|
|
|
|
$this->assertSoftDeleted('categories', ['id' => $category1->id]);
|
|
$this->assertDatabaseHas('categories', ['id' => $category2->id, 'deleted_at' => null]);
|
|
$this->assertDatabaseHas('product_categories', [
|
|
'product_id' => $product->id,
|
|
'category_id' => $category2->id,
|
|
]);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| SLUG EDGE CASES
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('slug is generated correctly from name with ampersand', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Food & Beverage',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Food & Beverage',
|
|
'slug' => Str::slug('Food & Beverage'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with dots', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Mr. Category',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Mr. Category',
|
|
'slug' => Str::slug('Mr. Category'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with slashes', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Food/Drink',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Food/Drink',
|
|
'slug' => Str::slug('Food/Drink'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with commas', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Makanan, Minuman',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Makanan, Minuman',
|
|
'slug' => Str::slug('Makanan, Minuman'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with single quotes', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => "It's Category",
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => "It's Category",
|
|
'slug' => Str::slug("It's Category"),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with double quotes', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => '"Premium" Category',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => '"Premium" Category',
|
|
'slug' => Str::slug('"Premium" Category'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with exclamation mark', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Hot Sale!',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Hot Sale!',
|
|
'slug' => Str::slug('Hot Sale!'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with question mark', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Best Choice?',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Best Choice?',
|
|
'slug' => Str::slug('Best Choice?'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from all-caps name', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'ELECTRONICS',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'ELECTRONICS',
|
|
'slug' => Str::slug('ELECTRONICS'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with numbers and letters mixed', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'iPhone 15 Pro',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'iPhone 15 Pro',
|
|
'slug' => Str::slug('iPhone 15 Pro'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with dash', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Food-Grade',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Food-Grade',
|
|
'slug' => Str::slug('Food-Grade'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with underscore', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Food_Grade',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Food_Grade',
|
|
'slug' => Str::slug('Food_Grade'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with at symbol', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Category@Home',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Category@Home',
|
|
'slug' => Str::slug('Category@Home'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with hash symbol', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Category#1',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Category#1',
|
|
'slug' => Str::slug('Category#1'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with currency symbol', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Rp 50.000',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Rp 50.000',
|
|
'slug' => Str::slug('Rp 50.000'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with pipe symbol', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'A|B',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'A|B',
|
|
'slug' => Str::slug('A|B'),
|
|
]);
|
|
});
|
|
|
|
test('slug is generated correctly from name with mixed special chars', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'A & B (v2.0)!',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'A & B (v2.0)!',
|
|
'slug' => Str::slug('A & B (v2.0)!'),
|
|
]);
|
|
});
|
|
|
|
test('slug does not change when category is updated with same name', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create(['name' => 'Same Name', 'slug' => 'same-name']);
|
|
$originalSlug = $category->slug;
|
|
|
|
$this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Same Name',
|
|
]);
|
|
|
|
$category->refresh();
|
|
expect($category->slug)->toBe($originalSlug);
|
|
});
|
|
|
|
test('slug changes when category name changes', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create(['name' => 'Old Name', 'slug' => 'old-name']);
|
|
|
|
$this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'New Name',
|
|
]);
|
|
|
|
$category->refresh();
|
|
expect($category->slug)->toBe('new-name');
|
|
expect($category->slug)->not->toBe('old-name');
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| AUTHORIZATION - GUEST CANNOT PERFORM ACTIONS
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('guest cannot create category', function () {
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Unauthorized',
|
|
]);
|
|
|
|
$response->assertRedirect(route('login'));
|
|
$this->assertDatabaseMissing('categories', ['name' => 'Unauthorized']);
|
|
});
|
|
|
|
test('guest cannot update category', function () {
|
|
$category = Category::factory()->create();
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Unauthorized Update',
|
|
]);
|
|
|
|
$response->assertRedirect(route('login'));
|
|
});
|
|
|
|
test('guest cannot delete category', function () {
|
|
$category = Category::factory()->create();
|
|
|
|
$response = $this->delete(route('admin.master.categories.destroy', $category));
|
|
|
|
$response->assertRedirect(route('login'));
|
|
$this->assertDatabaseHas('categories', ['id' => $category->id, 'deleted_at' => null]);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| DATA INTEGRITY
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('created category has correct timestamps', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Timestamp Test',
|
|
]);
|
|
|
|
$category = Category::where('name', 'Timestamp Test')->first();
|
|
expect($category->created_at)->not->toBeNull();
|
|
expect($category->updated_at)->not->toBeNull();
|
|
});
|
|
|
|
test('updated category has updated timestamp changed', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
$originalUpdatedAt = $category->updated_at;
|
|
|
|
sleep(1);
|
|
|
|
$this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Timestamp Changed',
|
|
]);
|
|
|
|
$category->refresh();
|
|
expect($category->updated_at->gt($originalUpdatedAt))->toBeTrue();
|
|
});
|
|
|
|
test('category ID is auto-incremented', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'First']);
|
|
$first = Category::where('name', 'First')->first();
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'Second']);
|
|
$second = Category::where('name', 'Second')->first();
|
|
|
|
expect($second->id)->toBe($first->id + 1);
|
|
});
|
|
|
|
test('category factory creates valid category', function () {
|
|
$category = Category::factory()->create();
|
|
|
|
expect($category->name)->not->toBeEmpty();
|
|
expect($category->slug)->not->toBeEmpty();
|
|
expect($category->id)->toBeInt();
|
|
});
|
|
|
|
test('category factory creates unique names', function () {
|
|
$categories = Category::factory()->count(20)->create();
|
|
|
|
$names = $categories->pluck('name')->toArray();
|
|
expect($names)->toHaveCount(count(array_unique($names)));
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| SOFT DELETE & RESTORE
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('category can be restored after soft delete', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create(['name' => 'Restored Category']);
|
|
$category->delete();
|
|
|
|
$this->assertSoftDeleted('categories', ['id' => $category->id]);
|
|
|
|
$category->restore();
|
|
|
|
$this->assertDatabaseHas('categories', ['id' => $category->id, 'deleted_at' => null]);
|
|
});
|
|
|
|
test('restored category appears in index again', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create(['name' => 'Restored Category']);
|
|
$category->delete();
|
|
|
|
$response = $this->get(route('admin.master.categories.index'));
|
|
$response->assertInertia(fn (Assert $page) => $page
|
|
->component('admin/master/category/index')
|
|
->has('categories.data', 0)
|
|
->where('categories.total', 0)
|
|
->where('categories.current_page', 1)
|
|
->where('categories.per_page', 25)
|
|
);
|
|
|
|
$category->restore();
|
|
|
|
$response = $this->get(route('admin.master.categories.index'));
|
|
$response->assertInertia(fn (Assert $page) => $page
|
|
->component('admin/master/category/index')
|
|
->has('categories.data', 1)
|
|
->where('categories.total', 1)
|
|
->where('categories.current_page', 1)
|
|
->where('categories.per_page', 25)
|
|
->where('categories.data.0.name', 'Restored Category')
|
|
);
|
|
});
|
|
|
|
test('restored category can be updated', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create(['name' => 'Before Restore']);
|
|
$category->delete();
|
|
$category->restore();
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'After Restore',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$category->refresh();
|
|
expect($category->name)->toBe('After Restore');
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| REALISTIC USER SCENARIOS
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('user creates category then immediately edits it', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'Draft Category']);
|
|
$category = Category::where('name', 'Draft Category')->first();
|
|
|
|
$this->put(route('admin.master.categories.update', $category), ['name' => 'Final Category']);
|
|
|
|
$category->refresh();
|
|
expect($category->name)->toBe('Final Category');
|
|
expect($category->slug)->toBe('final-category');
|
|
});
|
|
|
|
test('user creates multiple categories and deletes one', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'Keep']);
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'Delete Me']);
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'Also Keep']);
|
|
|
|
$toDelete = Category::where('name', 'Delete Me')->first();
|
|
$this->delete(route('admin.master.categories.destroy', $toDelete));
|
|
|
|
$response = $this->get(route('admin.master.categories.index'));
|
|
$response->assertOk();
|
|
$response->assertInertia(fn (Assert $page) => $page
|
|
->component('admin/master/category/index')
|
|
->has('categories.data', 2)
|
|
->where('categories.total', 2)
|
|
->where('categories.current_page', 1)
|
|
->where('categories.per_page', 25)
|
|
);
|
|
});
|
|
|
|
test('user renames category to match another existing category name', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
Category::factory()->create(['name' => 'Target Name']);
|
|
$category = Category::factory()->create(['name' => 'Source Name']);
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Target Name',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('user creates category with Indonesian characters', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Makanan Khas Jawa',
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Makanan Khas Jawa',
|
|
'slug' => 'makanan-khas-jawa',
|
|
]);
|
|
});
|
|
|
|
test('user tries to create category without submitting any data', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), []);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('user tries to update category without submitting any data', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$response = $this->put(route('admin.master.categories.update', $category), []);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('user rapidly submits same category creation twice', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'Rapid Submit']);
|
|
$response = $this->post(route('admin.master.categories.store'), ['name' => 'Rapid Submit']);
|
|
|
|
$response->assertSessionHasErrors('name');
|
|
$this->assertDatabaseCount('categories', 1);
|
|
});
|
|
|
|
test('user creates category with name containing email-like pattern', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'user@example.com']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'user@example.com',
|
|
'slug' => Str::slug('user@example.com'),
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing URL-like pattern', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'https://example.com']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'https://example.com',
|
|
'slug' => Str::slug('https://example.com'),
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing date-like pattern', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => '2024-01-15']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => '2024-01-15',
|
|
'slug' => '2024-01-15',
|
|
]);
|
|
});
|
|
|
|
test('user creates category with very short name', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), ['name' => 'X']);
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'X',
|
|
'slug' => 'x',
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing multiple dashes', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'A--B']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'A--B',
|
|
'slug' => Str::slug('A--B'),
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing mixed case and numbers', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'iPhone15ProMax']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'iPhone15ProMax',
|
|
'slug' => Str::slug('iPhone15ProMax'),
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing only spaces and numbers', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), ['name' => ' 123 ']);
|
|
$response->assertSessionHasNoErrors();
|
|
});
|
|
|
|
test('user creates category with name containing very long single word', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$name = str_repeat('a', 50);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), ['name' => $name]);
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => $name,
|
|
'slug' => $name,
|
|
]);
|
|
});
|
|
|
|
test('user creates category then creates another with similar name', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'Makanan']);
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'Minuman']);
|
|
|
|
$this->assertDatabaseCount('categories', 2);
|
|
$this->assertDatabaseHas('categories', ['name' => 'Makanan', 'slug' => 'makanan']);
|
|
$this->assertDatabaseHas('categories', ['name' => 'Minuman', 'slug' => 'minuman']);
|
|
});
|
|
|
|
test('user creates category with name containing curly braces', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => '{code}']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => '{code}',
|
|
'slug' => Str::slug('{code}'),
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing angle brackets', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => '<html>']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => '<html>',
|
|
'slug' => Str::slug('<html>'),
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing semicolon', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'A;B']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'A;B',
|
|
'slug' => Str::slug('A;B'),
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing colon', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'Time: Now']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Time: Now',
|
|
'slug' => Str::slug('Time: Now'),
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing backtick', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => '`Code`']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => '`Code`',
|
|
'slug' => Str::slug('`Code`'),
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing tilde', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'Caf~']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Caf~',
|
|
'slug' => Str::slug('Caf~'),
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing caret', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'A^B']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'A^B',
|
|
'slug' => Str::slug('A^B'),
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing percentage', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => '100% Natural']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => '100% Natural',
|
|
'slug' => Str::slug('100% Natural'),
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing regex special characters', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), ['name' => '.*+?^${}()|[]\\']);
|
|
$response->assertSessionHasNoErrors();
|
|
});
|
|
|
|
test('user creates category with name containing superscript', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), ['name' => 'E=mc2']);
|
|
$response->assertSessionHasNoErrors();
|
|
});
|
|
|
|
test('user creates category with name containing only newlines', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), ['name' => "\n\n\n"]);
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('user creates category with name containing only tabs', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), ['name' => "\t\t\t"]);
|
|
$response->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('user creates category with name containing mixed whitespace and visible chars', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->post(route('admin.master.categories.store'), ['name' => " \t Hello \n World "]);
|
|
$response->assertSessionHasNoErrors();
|
|
|
|
$category = DB::table('categories')->first();
|
|
expect($category->name)->not->toBeEmpty();
|
|
});
|
|
|
|
test('user creates category with name containing plus sign', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'A+B']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'A+B',
|
|
'slug' => Str::slug('A+B'),
|
|
]);
|
|
});
|
|
|
|
test('user creates category with name containing equals sign', function () {
|
|
$user = giveCategoryPermissions();
|
|
$this->actingAs($user);
|
|
|
|
$this->post(route('admin.master.categories.store'), ['name' => 'A=B']);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'A=B',
|
|
'slug' => Str::slug('A=B'),
|
|
]);
|
|
});
|