refactor(emoji): rename variables for clarity in EmojiAlias and EmojiCategory controllers

Updated variable names in the EmojiAliasController and EmojiCategoryController to improve code readability. Changed instances of `$emojiAlias` and `$emojiCategory` to `$alias` and `$category`, respectively, in the show, update, and destroy methods. Additionally, updated the UpdateEmojiAliasRequest to reflect the new variable naming convention. This enhances consistency and clarity across the codebase.
This commit is contained in:
Yury Pikhtarev 2025-07-02 03:10:04 +04:00
commit 6c491be4e9
No known key found for this signature in database
6 changed files with 920 additions and 18 deletions

View file

@ -53,37 +53,37 @@ class EmojiAliasController extends Controller
/**
* Display the specified resource.
*/
public function show(EmojiAlias $emojiAlias, Request $request)
public function show(EmojiAlias $alias, Request $request)
{
$emojiAlias->load(['emoji' => function ($query) {
$alias->load(['emoji' => function ($query) {
$query->with('category');
}]);
return new EmojiAliasResource($emojiAlias);
return new EmojiAliasResource($alias);
}
/**
* Update the specified resource in storage.
*/
public function update(UpdateEmojiAliasRequest $request, EmojiAlias $emojiAlias)
public function update(UpdateEmojiAliasRequest $request, EmojiAlias $alias)
{
$emojiAlias->update($request->validated());
$alias->update($request->validated());
if ($request->get('with_emoji')) {
$emojiAlias->load(['emoji' => function ($query) {
$alias->load(['emoji' => function ($query) {
$query->with('category');
}]);
}
return new EmojiAliasResource($emojiAlias);
return new EmojiAliasResource($alias);
}
/**
* Remove the specified resource from storage.
*/
public function destroy(EmojiAlias $emojiAlias)
public function destroy(EmojiAlias $alias)
{
$emojiAlias->delete();
$alias->delete();
return response()->json(null, 204);
}

View file

@ -44,9 +44,9 @@ class EmojiCategoryController extends Controller
/**
* Display the specified resource.
*/
public function show(EmojiCategory $emojiCategory, Request $request)
public function show(EmojiCategory $category, Request $request)
{
$emojiCategory->load([
$category->load([
'emojis' => function ($query) use ($request) {
$query->orderBy('display_order');
if ($request->get('with_aliases')) {
@ -55,25 +55,25 @@ class EmojiCategoryController extends Controller
},
]);
return new EmojiCategoryResource($emojiCategory);
return new EmojiCategoryResource($category);
}
/**
* Update the specified resource in storage.
*/
public function update(UpdateEmojiCategoryRequest $request, EmojiCategory $emojiCategory)
public function update(UpdateEmojiCategoryRequest $request, EmojiCategory $category)
{
$emojiCategory->update($request->validated());
$category->update($request->validated());
return new EmojiCategoryResource($emojiCategory);
return new EmojiCategoryResource($category);
}
/**
* Remove the specified resource from storage.
*/
public function destroy(EmojiCategory $emojiCategory)
public function destroy(EmojiCategory $category)
{
$emojiCategory->delete();
$category->delete();
return response()->json(null, 204);
}

View file

@ -22,7 +22,7 @@ class UpdateEmojiAliasRequest extends FormRequest
*/
public function rules(): array
{
$aliasId = $this->route('emoji_alias')->id;
$aliasId = $this->route('alias')->id;
return [
'emoji_id' => 'sometimes|exists:emojis,id',

View file

@ -0,0 +1,347 @@
<?php
use App\Models\Emoji;
use App\Models\EmojiAlias;
use App\Models\EmojiCategory;
describe('Emoji Alias API Endpoints', function () {
test('can list aliases', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
EmojiAlias::factory()->count(3)->create(['emoji_id' => $emoji->id]);
$response = $this->getJson('/api/emoji/aliases');
$response->assertOk()
->assertJsonStructure([
'data' => [
'*' => [
'id',
'alias',
'created_at',
'updated_at',
],
],
'links',
'meta',
])
->assertJsonCount(3, 'data');
});
test('can filter aliases by emoji', function () {
$category = EmojiCategory::factory()->create();
$emoji1 = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$emoji2 = Emoji::factory()->create(['emoji_category_id' => $category->id]);
EmojiAlias::factory()->count(2)->create(['emoji_id' => $emoji1->id]);
EmojiAlias::factory()->count(3)->create(['emoji_id' => $emoji2->id]);
$response = $this->getJson("/api/emoji/aliases?emoji_id={$emoji1->id}");
$response->assertOk()
->assertJsonCount(2, 'data');
});
test('can search aliases', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
EmojiAlias::factory()->create([
'emoji_id' => $emoji->id,
'alias' => ':happy:',
]);
EmojiAlias::factory()->create([
'emoji_id' => $emoji->id,
'alias' => ':sad:',
]);
$response = $this->getJson('/api/emoji/aliases?search=happy');
$response->assertOk()
->assertJsonCount(1, 'data')
->assertJsonPath('data.0.alias', ':happy:');
});
test('can include emoji and category with aliases', function () {
$category = EmojiCategory::factory()->create(['title' => 'Test Category']);
$emoji = Emoji::factory()->create([
'emoji_category_id' => $category->id,
'title' => 'Test Emoji',
]);
EmojiAlias::factory()->create(['emoji_id' => $emoji->id]);
$response = $this->getJson('/api/emoji/aliases?with_emoji=1');
$response->assertOk()
->assertJsonPath('data.0.emoji.title', 'Test Emoji')
->assertJsonPath('data.0.emoji.category.title', 'Test Category');
});
test('can get specific alias', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$alias = EmojiAlias::factory()->create([
'emoji_id' => $emoji->id,
'alias' => ':test_alias:',
]);
$response = $this->getJson("/api/emoji/aliases/{$alias->id}");
$response->assertOk()
->assertJsonPath('data.alias', ':test_alias:')
->assertJsonStructure([
'data' => [
'id',
'alias',
'emoji',
'created_at',
'updated_at',
],
]);
});
test('returns 404 for non-existent alias', function () {
$response = $this->getJson('/api/emoji/aliases/999');
$response->assertNotFound();
});
test('can create alias', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$data = [
'emoji_id' => $emoji->id,
'alias' => ':new_alias:',
];
$response = $this->postJson('/api/emoji/aliases', $data);
$response->assertCreated()
->assertJsonPath('data.alias', ':new_alias:')
->assertJsonPath('data.emoji', null); // Not loaded by default
$this->assertDatabaseHas('emoji_aliases', [
'emoji_id' => $emoji->id,
'alias' => ':new_alias:',
]);
});
test('validates required fields when creating alias', function () {
$response = $this->postJson('/api/emoji/aliases', []);
$response->assertUnprocessable()
->assertJsonValidationErrors(['emoji_id', 'alias']);
});
test('validates alias format', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$response = $this->postJson('/api/emoji/aliases', [
'emoji_id' => $emoji->id,
'alias' => 'invalid-format',
]);
$response->assertUnprocessable()
->assertJsonValidationErrors(['alias']);
});
test('validates unique alias', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
EmojiAlias::factory()->create([
'emoji_id' => $emoji->id,
'alias' => ':existing:',
]);
$response = $this->postJson('/api/emoji/aliases', [
'emoji_id' => $emoji->id,
'alias' => ':existing:',
]);
$response->assertUnprocessable()
->assertJsonValidationErrors(['alias']);
});
test('validates emoji exists', function () {
$response = $this->postJson('/api/emoji/aliases', [
'emoji_id' => 999,
'alias' => ':valid_alias:',
]);
$response->assertUnprocessable()
->assertJsonValidationErrors(['emoji_id']);
});
test('prevents alias from conflicting with emoji shortcode', function () {
$category = EmojiCategory::factory()->create();
$emoji1 = Emoji::factory()->create([
'emoji_category_id' => $category->id,
'emoji_shortcode' => ':existing_emoji:',
]);
$emoji2 = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$response = $this->postJson('/api/emoji/aliases', [
'emoji_id' => $emoji2->id,
'alias' => ':existing_emoji:',
]);
$response->assertUnprocessable()
->assertJsonValidationErrors(['alias']);
});
test('can update alias', function () {
$category = EmojiCategory::factory()->create();
$emoji1 = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$emoji2 = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$alias = EmojiAlias::factory()->create(['emoji_id' => $emoji1->id]);
$data = [
'emoji_id' => $emoji2->id,
'alias' => ':updated_alias:',
];
$response = $this->patchJson("/api/emoji/aliases/{$alias->id}", $data);
$response->assertOk()
->assertJsonPath('data.alias', ':updated_alias:');
$this->assertDatabaseHas('emoji_aliases', [
'id' => $alias->id,
'emoji_id' => $emoji2->id,
'alias' => ':updated_alias:',
]);
});
test('can partially update alias', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$alias = EmojiAlias::factory()->create([
'emoji_id' => $emoji->id,
'alias' => ':original:',
]);
$response = $this->patchJson("/api/emoji/aliases/{$alias->id}", [
'alias' => ':updated:',
]);
$response->assertOk()
->assertJsonPath('data.alias', ':updated:');
// emoji_id should remain unchanged
$this->assertDatabaseHas('emoji_aliases', [
'id' => $alias->id,
'emoji_id' => $emoji->id,
'alias' => ':updated:',
]);
});
test('can delete alias', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$alias = EmojiAlias::factory()->create(['emoji_id' => $emoji->id]);
$response = $this->deleteJson("/api/emoji/aliases/{$alias->id}");
$response->assertNoContent();
$this->assertDatabaseMissing('emoji_aliases', ['id' => $alias->id]);
// Emoji should still exist
$this->assertDatabaseHas('emojis', ['id' => $emoji->id]);
});
test('supports pagination', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
EmojiAlias::factory()->count(60)->create(['emoji_id' => $emoji->id]);
$response = $this->getJson('/api/emoji/aliases?per_page=20&page=2');
$response->assertOk()
->assertJsonPath('meta.current_page', 2)
->assertJsonPath('meta.per_page', 20)
->assertJsonCount(20, 'data');
});
test('aliases are ordered alphabetically', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
EmojiAlias::factory()->create(['emoji_id' => $emoji->id, 'alias' => ':zebra:']);
EmojiAlias::factory()->create(['emoji_id' => $emoji->id, 'alias' => ':apple:']);
EmojiAlias::factory()->create(['emoji_id' => $emoji->id, 'alias' => ':banana:']);
$response = $this->getJson('/api/emoji/aliases');
$response->assertOk()
->assertJsonPath('data.0.alias', ':apple:')
->assertJsonPath('data.1.alias', ':banana:')
->assertJsonPath('data.2.alias', ':zebra:');
});
});
describe('Emoji Alias Search API', function () {
test('can search aliases using scout', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
EmojiAlias::factory()->create([
'emoji_id' => $emoji->id,
'alias' => ':happy:',
]);
EmojiAlias::factory()->create([
'emoji_id' => $emoji->id,
'alias' => ':sad:',
]);
$response = $this->getJson('/api/emoji/aliases/search?q=happy');
$response->assertOk()
->assertJsonStructure([
'data' => [
'*' => [
'id',
'alias',
'emoji',
],
],
]);
});
test('validates search query parameter', function () {
$response = $this->getJson('/api/emoji/aliases/search');
$response->assertUnprocessable()
->assertJsonValidationErrors(['q']);
});
test('validates search limit parameter', function () {
$response = $this->getJson('/api/emoji/aliases/search?q=test&limit=150');
$response->assertUnprocessable()
->assertJsonValidationErrors(['limit']);
});
test('can include emoji data in search results', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$alias = EmojiAlias::factory()->create(['emoji_id' => $emoji->id]);
$response = $this->getJson('/api/emoji/aliases/search?q=test&with_emoji=1');
$response->assertOk()
->assertJsonStructure([
'data' => [
'*' => [
'emoji' => [
'id',
'title',
'emoji_shortcode',
],
],
],
]);
});
});

View file

@ -0,0 +1,222 @@
<?php
use App\Models\Emoji;
use App\Models\EmojiCategory;
describe('Emoji Category API Endpoints', function () {
test('can list categories', function () {
EmojiCategory::factory()->count(3)->create();
$response = $this->getJson('/api/emoji/categories');
$response->assertOk()
->assertJsonStructure([
'data' => [
'*' => [
'id',
'title',
'display_order',
'created_at',
'updated_at',
],
],
])
->assertJsonCount(3, 'data');
});
test('can list categories with emoji counts', function () {
$category1 = EmojiCategory::factory()->create(['title' => 'Category 1']);
$category2 = EmojiCategory::factory()->create(['title' => 'Category 2']);
Emoji::factory()->count(5)->create(['emoji_category_id' => $category1->id]);
Emoji::factory()->count(3)->create(['emoji_category_id' => $category2->id]);
$response = $this->getJson('/api/emoji/categories?with_emojis=1');
$response->assertOk()
->assertJsonPath('data.0.emojis_count', 5)
->assertJsonPath('data.1.emojis_count', 3);
});
test('can list categories with full emoji data', function () {
$category = EmojiCategory::factory()->create();
Emoji::factory()->count(2)->create(['emoji_category_id' => $category->id]);
$response = $this->getJson('/api/emoji/categories?include_emojis=1');
$response->assertOk()
->assertJsonCount(2, 'data.0.emojis')
->assertJsonStructure([
'data' => [
'*' => [
'emojis' => [
'*' => [
'id',
'title',
'emoji_shortcode',
'emoji_text',
],
],
],
],
]);
});
test('can get specific category', function () {
$category = EmojiCategory::factory()->create([
'title' => 'Test Category',
'display_order' => 5,
]);
$response = $this->getJson("/api/emoji/categories/{$category->id}");
$response->assertOk()
->assertJsonPath('data.title', 'Test Category')
->assertJsonPath('data.display_order', 5)
->assertJsonStructure([
'data' => [
'id',
'title',
'display_order',
'emojis',
'created_at',
'updated_at',
],
]);
});
test('can get category with emoji aliases', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$response = $this->getJson("/api/emoji/categories/{$category->id}?with_aliases=1");
$response->assertOk()
->assertJsonStructure([
'data' => [
'emojis' => [
'*' => [
'aliases',
],
],
],
]);
});
test('returns 404 for non-existent category', function () {
$response = $this->getJson('/api/emoji/categories/999');
$response->assertNotFound();
});
test('can create category', function () {
$data = [
'title' => 'New Category',
'display_order' => 10,
];
$response = $this->postJson('/api/emoji/categories', $data);
$response->assertCreated()
->assertJsonPath('data.title', 'New Category')
->assertJsonPath('data.display_order', 10);
$this->assertDatabaseHas('emoji_categories', [
'title' => 'New Category',
'display_order' => 10,
]);
});
test('validates required fields when creating category', function () {
$response = $this->postJson('/api/emoji/categories', []);
$response->assertUnprocessable()
->assertJsonValidationErrors(['title', 'display_order']);
});
test('validates display order is non-negative', function () {
$response = $this->postJson('/api/emoji/categories', [
'title' => 'Test Category',
'display_order' => -1,
]);
$response->assertUnprocessable()
->assertJsonValidationErrors(['display_order']);
});
test('validates title length', function () {
$response = $this->postJson('/api/emoji/categories', [
'title' => str_repeat('a', 256),
'display_order' => 1,
]);
$response->assertUnprocessable()
->assertJsonValidationErrors(['title']);
});
test('can update category', function () {
$category = EmojiCategory::factory()->create();
$data = [
'title' => 'Updated Title',
'display_order' => 99,
];
$response = $this->patchJson("/api/emoji/categories/{$category->id}", $data);
$response->assertOk()
->assertJsonPath('data.title', 'Updated Title')
->assertJsonPath('data.display_order', 99);
$this->assertDatabaseHas('emoji_categories', [
'id' => $category->id,
'title' => 'Updated Title',
'display_order' => 99,
]);
});
test('can partially update category', function () {
$category = EmojiCategory::factory()->create([
'title' => 'Original Title',
'display_order' => 5,
]);
$response = $this->patchJson("/api/emoji/categories/{$category->id}", [
'title' => 'New Title',
]);
$response->assertOk()
->assertJsonPath('data.title', 'New Title')
->assertJsonPath('data.display_order', 5); // Should remain unchanged
});
test('can delete category', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$response = $this->deleteJson("/api/emoji/categories/{$category->id}");
$response->assertNoContent();
$this->assertDatabaseMissing('emoji_categories', ['id' => $category->id]);
// Emoji should still exist but with null category_id
$this->assertDatabaseHas('emojis', [
'id' => $emoji->id,
'emoji_category_id' => null,
]);
});
test('categories are ordered by display_order', function () {
EmojiCategory::factory()->create(['title' => 'Third', 'display_order' => 3]);
EmojiCategory::factory()->create(['title' => 'First', 'display_order' => 1]);
EmojiCategory::factory()->create(['title' => 'Second', 'display_order' => 2]);
$response = $this->getJson('/api/emoji/categories');
$response->assertOk()
->assertJsonPath('data.0.title', 'First')
->assertJsonPath('data.1.title', 'Second')
->assertJsonPath('data.2.title', 'Third');
});
});

View file

@ -0,0 +1,333 @@
<?php
use App\Models\Emoji;
use App\Models\EmojiAlias;
use App\Models\EmojiCategory;
describe('Emoji API Endpoints', function () {
test('can list emojis', function () {
$category = EmojiCategory::factory()->create();
$emojis = Emoji::factory()->count(3)->create(['emoji_category_id' => $category->id]);
$response = $this->getJson('/api/emoji/emojis');
$response->assertOk()
->assertJsonStructure([
'data' => [
'*' => [
'id',
'title',
'emoji_text',
'emoji_shortcode',
'image_url',
'sprite_mode',
'sprite_params',
'display_order',
'created_at',
'updated_at',
],
],
'links',
'meta',
])
->assertJsonCount(3, 'data');
});
test('can filter emojis by category', function () {
$category1 = EmojiCategory::factory()->create();
$category2 = EmojiCategory::factory()->create();
Emoji::factory()->count(2)->create(['emoji_category_id' => $category1->id]);
Emoji::factory()->count(3)->create(['emoji_category_id' => $category2->id]);
$response = $this->getJson("/api/emoji/emojis?category_id={$category1->id}");
$response->assertOk()
->assertJsonCount(2, 'data');
});
test('can search emojis', function () {
$category = EmojiCategory::factory()->create();
Emoji::factory()->create([
'title' => 'Happy Face',
'emoji_shortcode' => ':happy:',
'emoji_category_id' => $category->id,
]);
Emoji::factory()->create([
'title' => 'Sad Face',
'emoji_shortcode' => ':sad:',
'emoji_category_id' => $category->id,
]);
$response = $this->getJson('/api/emoji/emojis?search=happy');
$response->assertOk()
->assertJsonCount(1, 'data')
->assertJsonPath('data.0.title', 'Happy Face');
});
test('can include category and aliases with emojis', function () {
$category = EmojiCategory::factory()->create(['title' => 'Test Category']);
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
EmojiAlias::factory()->count(2)->create(['emoji_id' => $emoji->id]);
$response = $this->getJson('/api/emoji/emojis?with_category=1&with_aliases=1');
$response->assertOk()
->assertJsonPath('data.0.category.title', 'Test Category')
->assertJsonCount(2, 'data.0.aliases');
});
test('can get specific emoji', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create([
'title' => 'Test Emoji',
'emoji_shortcode' => ':test:',
'emoji_category_id' => $category->id,
]);
$response = $this->getJson("/api/emoji/emojis/{$emoji->id}");
$response->assertOk()
->assertJsonPath('data.title', 'Test Emoji')
->assertJsonPath('data.emoji_shortcode', ':test:')
->assertJsonStructure([
'data' => [
'id',
'title',
'emoji_shortcode',
'category',
'aliases',
],
]);
});
test('returns 404 for non-existent emoji', function () {
$response = $this->getJson('/api/emoji/emojis/999');
$response->assertNotFound();
});
test('can create unicode emoji', function () {
$category = EmojiCategory::factory()->create();
$data = [
'title' => 'Happy Face',
'emoji_text' => '😊',
'emoji_shortcode' => ':happy_face:',
'emoji_category_id' => $category->id,
'display_order' => 1,
];
$response = $this->postJson('/api/emoji/emojis', $data);
$response->assertCreated()
->assertJsonPath('data.title', 'Happy Face')
->assertJsonPath('data.emoji_text', '😊')
->assertJsonPath('data.emoji_shortcode', ':happy_face:');
$this->assertDatabaseHas('emojis', [
'title' => 'Happy Face',
'emoji_text' => '😊',
'emoji_shortcode' => ':happy_face:',
]);
});
test('can create custom image emoji', function () {
$category = EmojiCategory::factory()->create();
$data = [
'title' => 'Custom Emoji',
'emoji_shortcode' => ':custom:',
'image_url' => '/emojis/custom/custom.png',
'emoji_category_id' => $category->id,
'display_order' => 1,
];
$response = $this->postJson('/api/emoji/emojis', $data);
$response->assertCreated()
->assertJsonPath('data.title', 'Custom Emoji')
->assertJsonPath('data.image_url', '/emojis/custom/custom.png')
->assertJsonPath('data.emoji_text', null);
});
test('can create sprite emoji', function () {
$category = EmojiCategory::factory()->create();
$data = [
'title' => 'Sprite Emoji',
'emoji_shortcode' => ':sprite:',
'sprite_mode' => true,
'sprite_params' => [
'x' => 32,
'y' => 64,
'width' => 32,
'height' => 32,
'sheet' => 'emoji-sheet-1.png',
],
'emoji_category_id' => $category->id,
'display_order' => 1,
];
$response = $this->postJson('/api/emoji/emojis', $data);
$response->assertCreated()
->assertJsonPath('data.sprite_mode', true)
->assertJsonPath('data.sprite_params.x', 32)
->assertJsonPath('data.sprite_params.sheet', 'emoji-sheet-1.png');
});
test('validates required fields when creating emoji', function () {
$response = $this->postJson('/api/emoji/emojis', []);
$response->assertUnprocessable()
->assertJsonValidationErrors(['title', 'emoji_shortcode', 'display_order']);
});
test('validates emoji shortcode format', function () {
$category = EmojiCategory::factory()->create();
$response = $this->postJson('/api/emoji/emojis', [
'title' => 'Test',
'emoji_shortcode' => 'invalid-format',
'emoji_category_id' => $category->id,
'display_order' => 1,
]);
$response->assertUnprocessable()
->assertJsonValidationErrors(['emoji_shortcode']);
});
test('validates unique emoji shortcode', function () {
$category = EmojiCategory::factory()->create();
Emoji::factory()->create(['emoji_shortcode' => ':existing:']);
$response = $this->postJson('/api/emoji/emojis', [
'title' => 'Test',
'emoji_shortcode' => ':existing:',
'emoji_category_id' => $category->id,
'display_order' => 1,
]);
$response->assertUnprocessable()
->assertJsonValidationErrors(['emoji_shortcode']);
});
test('validates sprite params when sprite mode is enabled', function () {
$category = EmojiCategory::factory()->create();
$response = $this->postJson('/api/emoji/emojis', [
'title' => 'Test',
'emoji_shortcode' => ':test:',
'sprite_mode' => true,
'emoji_category_id' => $category->id,
'display_order' => 1,
]);
$response->assertUnprocessable()
->assertJsonValidationErrors([
'sprite_params.x',
'sprite_params.y',
'sprite_params.width',
'sprite_params.height',
'sprite_params.sheet',
]);
});
test('can update emoji', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$data = [
'title' => 'Updated Title',
'display_order' => 99,
];
$response = $this->patchJson("/api/emoji/emojis/{$emoji->id}", $data);
$response->assertOk()
->assertJsonPath('data.title', 'Updated Title')
->assertJsonPath('data.display_order', 99);
$this->assertDatabaseHas('emojis', [
'id' => $emoji->id,
'title' => 'Updated Title',
'display_order' => 99,
]);
});
test('can delete emoji', function () {
$category = EmojiCategory::factory()->create();
$emoji = Emoji::factory()->create(['emoji_category_id' => $category->id]);
$alias = EmojiAlias::factory()->create(['emoji_id' => $emoji->id]);
$response = $this->deleteJson("/api/emoji/emojis/{$emoji->id}");
$response->assertNoContent();
$this->assertDatabaseMissing('emojis', ['id' => $emoji->id]);
$this->assertDatabaseMissing('emoji_aliases', ['id' => $alias->id]);
});
test('supports pagination', function () {
$category = EmojiCategory::factory()->create();
Emoji::factory()->count(60)->create(['emoji_category_id' => $category->id]);
$response = $this->getJson('/api/emoji/emojis?per_page=20&page=2');
$response->assertOk()
->assertJsonPath('meta.current_page', 2)
->assertJsonPath('meta.per_page', 20)
->assertJsonCount(20, 'data');
});
});
describe('Emoji Search API', function () {
test('can search emojis using scout', function () {
$category = EmojiCategory::factory()->create();
// Create emojis with different content
Emoji::factory()->create([
'title' => 'Happy Face',
'emoji_shortcode' => ':happy:',
'emoji_text' => '😊',
'emoji_category_id' => $category->id,
]);
Emoji::factory()->create([
'title' => 'Sad Face',
'emoji_shortcode' => ':sad:',
'emoji_text' => '😢',
'emoji_category_id' => $category->id,
]);
$response = $this->getJson('/api/emoji/emojis/search?q=happy');
$response->assertOk()
->assertJsonStructure([
'data' => [
'*' => [
'id',
'title',
'emoji_shortcode',
'emoji_text',
],
],
]);
});
test('validates search query parameter', function () {
$response = $this->getJson('/api/emoji/emojis/search');
$response->assertUnprocessable()
->assertJsonValidationErrors(['q']);
});
test('validates search limit parameter', function () {
$response = $this->getJson('/api/emoji/emojis/search?q=test&limit=150');
$response->assertUnprocessable()
->assertJsonValidationErrors(['limit']);
});
});