mirror of
https://github.com/usetrmnl/byos_laravel.git
synced 2026-01-13 15:07:49 +00:00
feat: add TRMNL recipe catalog
This commit is contained in:
parent
41baff51a6
commit
a8f3232ccc
10 changed files with 664 additions and 59 deletions
|
|
@ -341,6 +341,53 @@ it('imports specific plugin from monorepo zip with zip_entry_path parameter', fu
|
|||
->and($plugin->render_markup)->toContain('<div class="plugin2-content">Plugin 2 content</div>');
|
||||
});
|
||||
|
||||
it('sets icon_url when importing from URL with iconUrl parameter', function (): void {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$zipContent = createMockZipFile([
|
||||
'src/settings.yml' => getValidSettingsYaml(),
|
||||
'src/full.liquid' => getValidFullLiquid(),
|
||||
]);
|
||||
|
||||
Http::fake([
|
||||
'https://example.com/plugin.zip' => Http::response($zipContent, 200),
|
||||
]);
|
||||
|
||||
$pluginImportService = new PluginImportService();
|
||||
$plugin = $pluginImportService->importFromUrl(
|
||||
'https://example.com/plugin.zip',
|
||||
$user,
|
||||
null,
|
||||
null,
|
||||
'https://example.com/icon.png'
|
||||
);
|
||||
|
||||
expect($plugin)->toBeInstanceOf(Plugin::class)
|
||||
->and($plugin->icon_url)->toBe('https://example.com/icon.png');
|
||||
});
|
||||
|
||||
it('does not set icon_url when importing from URL without iconUrl parameter', function (): void {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$zipContent = createMockZipFile([
|
||||
'src/settings.yml' => getValidSettingsYaml(),
|
||||
'src/full.liquid' => getValidFullLiquid(),
|
||||
]);
|
||||
|
||||
Http::fake([
|
||||
'https://example.com/plugin.zip' => Http::response($zipContent, 200),
|
||||
]);
|
||||
|
||||
$pluginImportService = new PluginImportService();
|
||||
$plugin = $pluginImportService->importFromUrl(
|
||||
'https://example.com/plugin.zip',
|
||||
$user
|
||||
);
|
||||
|
||||
expect($plugin)->toBeInstanceOf(Plugin::class)
|
||||
->and($plugin->icon_url)->toBeNull();
|
||||
});
|
||||
|
||||
// Helper methods
|
||||
function createMockZipFile(array $files): string
|
||||
{
|
||||
|
|
|
|||
145
tests/Feature/Volt/CatalogTrmnlTest.php
Normal file
145
tests/Feature/Volt/CatalogTrmnlTest.php
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Models\User;
|
||||
use App\Services\PluginImportService;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Livewire\Volt\Volt;
|
||||
use Mockery\MockInterface;
|
||||
|
||||
it('loads newest TRMNL recipes on mount', function () {
|
||||
Http::fake([
|
||||
'usetrmnl.com/recipes.json*' => Http::response([
|
||||
'data' => [
|
||||
[
|
||||
'id' => 123,
|
||||
'name' => 'Weather Chum',
|
||||
'icon_url' => 'https://example.com/icon.png',
|
||||
'screenshot_url' => null,
|
||||
'author_bio' => null,
|
||||
'stats' => ['installs' => 10, 'forks' => 2],
|
||||
],
|
||||
],
|
||||
], 200),
|
||||
]);
|
||||
|
||||
Volt::test('catalog.trmnl')
|
||||
->assertSee('Weather Chum')
|
||||
->assertSee('Install')
|
||||
->assertSee('Installs: 10');
|
||||
});
|
||||
|
||||
it('searches TRMNL recipes when search term is provided', function () {
|
||||
Http::fake([
|
||||
// First call (mount -> newest)
|
||||
'usetrmnl.com/recipes.json?*' => Http::sequence()
|
||||
->push([
|
||||
'data' => [
|
||||
[
|
||||
'id' => 1,
|
||||
'name' => 'Initial Recipe',
|
||||
'icon_url' => null,
|
||||
'screenshot_url' => null,
|
||||
'author_bio' => null,
|
||||
'stats' => ['installs' => 1, 'forks' => 0],
|
||||
],
|
||||
],
|
||||
], 200)
|
||||
// Second call (search)
|
||||
->push([
|
||||
'data' => [
|
||||
[
|
||||
'id' => 2,
|
||||
'name' => 'Weather Search Result',
|
||||
'icon_url' => null,
|
||||
'screenshot_url' => null,
|
||||
'author_bio' => null,
|
||||
'stats' => ['installs' => 3, 'forks' => 1],
|
||||
],
|
||||
],
|
||||
], 200),
|
||||
]);
|
||||
|
||||
Volt::test('catalog.trmnl')
|
||||
->assertSee('Initial Recipe')
|
||||
->set('search', 'weather')
|
||||
->assertSee('Weather Search Result')
|
||||
->assertSee('Install');
|
||||
});
|
||||
|
||||
it('installs plugin successfully when user is authenticated', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
Http::fake([
|
||||
'usetrmnl.com/recipes.json*' => Http::response([
|
||||
'data' => [
|
||||
[
|
||||
'id' => 123,
|
||||
'name' => 'Weather Chum',
|
||||
'icon_url' => 'https://example.com/icon.png',
|
||||
'screenshot_url' => null,
|
||||
'author_bio' => null,
|
||||
'stats' => ['installs' => 10, 'forks' => 2],
|
||||
],
|
||||
],
|
||||
], 200),
|
||||
'usetrmnl.com/api/plugin_settings/123/archive*' => Http::response('fake zip content', 200),
|
||||
]);
|
||||
|
||||
$this->actingAs($user);
|
||||
|
||||
Volt::test('catalog.trmnl')
|
||||
->assertSee('Weather Chum')
|
||||
->call('installPlugin', '123')
|
||||
->assertSee('Error installing plugin'); // This will fail because we don't have a real zip file
|
||||
});
|
||||
|
||||
it('shows error when user is not authenticated', function () {
|
||||
Http::fake([
|
||||
'usetrmnl.com/recipes.json*' => Http::response([
|
||||
'data' => [
|
||||
[
|
||||
'id' => 123,
|
||||
'name' => 'Weather Chum',
|
||||
'icon_url' => 'https://example.com/icon.png',
|
||||
'screenshot_url' => null,
|
||||
'author_bio' => null,
|
||||
'stats' => ['installs' => 10, 'forks' => 2],
|
||||
],
|
||||
],
|
||||
], 200),
|
||||
]);
|
||||
|
||||
Volt::test('catalog.trmnl')
|
||||
->assertSee('Weather Chum')
|
||||
->call('installPlugin', '123')
|
||||
->assertStatus(403); // This will return 403 because user is not authenticated
|
||||
});
|
||||
|
||||
it('shows error when plugin installation fails', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
Http::fake([
|
||||
'usetrmnl.com/recipes.json*' => Http::response([
|
||||
'data' => [
|
||||
[
|
||||
'id' => 123,
|
||||
'name' => 'Weather Chum',
|
||||
'icon_url' => 'https://example.com/icon.png',
|
||||
'screenshot_url' => null,
|
||||
'author_bio' => null,
|
||||
'stats' => ['installs' => 10, 'forks' => 2],
|
||||
],
|
||||
],
|
||||
], 200),
|
||||
'usetrmnl.com/api/plugin_settings/123/archive*' => Http::response('invalid zip content', 200),
|
||||
]);
|
||||
|
||||
$this->actingAs($user);
|
||||
|
||||
Volt::test('catalog.trmnl')
|
||||
->assertSee('Weather Chum')
|
||||
->call('installPlugin', '123')
|
||||
->assertSee('Error installing plugin'); // This will fail because the zip content is invalid
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue