From 344e6ba5c38341911787bad6c3ea934272cff56d Mon Sep 17 00:00:00 2001 From: Andrey Helldar Date: Sun, 31 Aug 2025 00:21:18 +0300 Subject: [PATCH] Added tests for real feeds --- testbench.yaml | 2 +- .../snapshots/Feature/SitemapTest/export.snap | 13 ++++ .../snapshots/Feature/YandexTest/export.snap | 51 +++++++++++++ tests/Feature/FullTest.php | 5 +- tests/Feature/PartialTest.php | 9 +-- tests/Feature/SitemapTest.php | 19 +++++ tests/Feature/YandexTest.php | 19 +++++ tests/Helpers/models.php | 21 ++++++ workbench/app/Data/ProductFakeData.php | 73 +++++++++++++++++++ workbench/app/Feeds/Items/SitemapFeedItem.php | 27 +++++++ workbench/app/Feeds/Items/YandexFeedItem.php | 46 ++++++++++++ workbench/app/Feeds/SitemapFeed.php | 49 +++++++++++++ workbench/app/Feeds/YandexFeed.php | 67 +++++++++++++++++ workbench/app/Models/News.php | 1 + workbench/app/Models/Product.php | 30 ++++++++ workbench/config/emails.php | 7 ++ workbench/config/feeds.php | 11 +-- .../database/factories/ProductFactory.php | 34 +++++++++ ...025_08_30_235243_create_products_table.php | 30 ++++++++ workbench/routes/web.php | 7 ++ 20 files changed, 505 insertions(+), 16 deletions(-) create mode 100644 tests/.pest/snapshots/Feature/SitemapTest/export.snap create mode 100644 tests/.pest/snapshots/Feature/YandexTest/export.snap create mode 100644 tests/Feature/SitemapTest.php create mode 100644 tests/Feature/YandexTest.php create mode 100644 tests/Helpers/models.php create mode 100644 workbench/app/Data/ProductFakeData.php create mode 100644 workbench/app/Feeds/Items/SitemapFeedItem.php create mode 100644 workbench/app/Feeds/Items/YandexFeedItem.php create mode 100644 workbench/app/Feeds/SitemapFeed.php create mode 100644 workbench/app/Feeds/YandexFeed.php create mode 100644 workbench/app/Models/Product.php create mode 100644 workbench/config/emails.php create mode 100644 workbench/database/factories/ProductFactory.php create mode 100644 workbench/database/migrations/2025_08_30_235243_create_products_table.php create mode 100644 workbench/routes/web.php diff --git a/testbench.yaml b/testbench.yaml index 4efff7d..69af6bc 100644 --- a/testbench.yaml +++ b/testbench.yaml @@ -9,7 +9,7 @@ migrations: workbench: install: false discovers: - web: false + web: true api: false config: true commands: false diff --git a/tests/.pest/snapshots/Feature/SitemapTest/export.snap b/tests/.pest/snapshots/Feature/SitemapTest/export.snap new file mode 100644 index 0000000..715d2d3 --- /dev/null +++ b/tests/.pest/snapshots/Feature/SitemapTest/export.snap @@ -0,0 +1,13 @@ + + + + http://localhost/products/GD-PRDCT-1 + 2025-08-31T20:00:00+00:00 + 0.9 + + + http://localhost/products/GD-PRDCT-2 + 2025-08-30T19:00:00+00:00 + 0.9 + + diff --git a/tests/.pest/snapshots/Feature/YandexTest/export.snap b/tests/.pest/snapshots/Feature/YandexTest/export.snap new file mode 100644 index 0000000..58988d2 --- /dev/null +++ b/tests/.pest/snapshots/Feature/YandexTest/export.snap @@ -0,0 +1,51 @@ + + + + Laravel + Laravel + http://localhost + Laravel + test@example.com + + + + + Домашние майки + Велосипедки + Ремни + + + + http://localhost/products/GD-PRDCT-1 + GD-PRDCT-1 + Some 1 + Some description 1 + true + 100 + RUR + The Best + + + http://localhost/products/GD-PRDCT-2 + GD-PRDCT-2 + Some 2 + Some description 2 + true + 250 + RUR + The Best + + + http://localhost/products/GD-PRDCT-3 + GD-PRDCT-3 + Some 3 + Some description 3 + true + 400 + RUR + The Best + + + + + \ No newline at end of file diff --git a/tests/Feature/FullTest.php b/tests/Feature/FullTest.php index 4fd9723..a41d856 100644 --- a/tests/Feature/FullTest.php +++ b/tests/Feature/FullTest.php @@ -5,16 +5,13 @@ use DragonCode\LaravelFeed\Console\Commands\FeedGenerateCommand; use Workbench\App\Data\NewsFakeData; use Workbench\App\Feeds\FilledFeed; -use Workbench\App\Models\News; use function Pest\Laravel\artisan; test('export', function (bool $pretty) { setPrettyXml($pretty); - News::factory()->count(3)->sequence( - ...NewsFakeData::toArray() - )->createMany(); + createNews(...NewsFakeData::toArray()); $feed = app()->make(FilledFeed::class); diff --git a/tests/Feature/PartialTest.php b/tests/Feature/PartialTest.php index d9560c6..908e67e 100644 --- a/tests/Feature/PartialTest.php +++ b/tests/Feature/PartialTest.php @@ -5,20 +5,17 @@ use DragonCode\LaravelFeed\Console\Commands\FeedGenerateCommand; use Workbench\App\Data\NewsFakeData; use Workbench\App\Feeds\FilledFeed; -use Workbench\App\Models\News; use function Pest\Laravel\artisan; test('export', function (bool $pretty) { setPrettyXml($pretty); - News::factory()->count(5)->sequence(fn () => [ + createNews(static fn () => [ 'updated_at' => fake()->dateTimeBetween(endDate: '-1 month'), - ])->createMany(); + ]); - News::factory()->count(3)->sequence( - ...NewsFakeData::toArray() - )->createMany(); + createNews(...NewsFakeData::toArray()); $feed = app()->make(FilledFeed::class); diff --git a/tests/Feature/SitemapTest.php b/tests/Feature/SitemapTest.php new file mode 100644 index 0000000..0547e85 --- /dev/null +++ b/tests/Feature/SitemapTest.php @@ -0,0 +1,19 @@ +make(SitemapFeed::class); + + artisan(FeedGenerateCommand::class)->run(); + + expect($feed->path())->toBeReadableFile(); + expect(file_get_contents($feed->path()))->toMatchSnapshot(); +}); diff --git a/tests/Feature/YandexTest.php b/tests/Feature/YandexTest.php new file mode 100644 index 0000000..3e8461f --- /dev/null +++ b/tests/Feature/YandexTest.php @@ -0,0 +1,19 @@ +make(YandexFeed::class); + + artisan(FeedGenerateCommand::class)->run(); + + expect($feed->path())->toBeReadableFile(); + expect(file_get_contents($feed->path()))->toMatchSnapshot(); +}); diff --git a/tests/Helpers/models.php b/tests/Helpers/models.php new file mode 100644 index 0000000..aec4cb1 --- /dev/null +++ b/tests/Helpers/models.php @@ -0,0 +1,21 @@ +count(3)->sequence( + ...$sequence + )->createMany(); +} + +function createProducts(): void +{ + Product::factory()->count(3)->sequence( + ...ProductFakeData::toArray() + )->create(); +} diff --git a/workbench/app/Data/ProductFakeData.php b/workbench/app/Data/ProductFakeData.php new file mode 100644 index 0000000..5a3ba43 --- /dev/null +++ b/workbench/app/Data/ProductFakeData.php @@ -0,0 +1,73 @@ + 'GD-PRDCT-1', + 'title' => 'Some 1', + 'description' => 'Some description 1', + + 'price' => 100, + 'quantity' => 5, + 'currency' => 'USD', + + 'brand' => 'The Best', + + 'images' => json_encode([ + 'https://via.placeholder.com/640x480.png/00ff55?text=s1', + ]), + + 'created_at' => '2025-08-31 00:00:00', + 'updated_at' => '2025-08-31 20:00:00', + ], + [ + 'article' => 'GD-PRDCT-2', + 'title' => 'Some 2', + 'description' => 'Some description 2', + + 'price' => 250, + 'quantity' => 20, + 'currency' => 'USD', + + 'brand' => 'The Best', + + 'images' => json_encode([ + 'https://via.placeholder.com/640x480.png/00ff55?text=s20', + 'https://via.placeholder.com/640x480.png/00ff55?text=s21', + 'https://via.placeholder.com/640x480.png/00ff55?text=s22', + ]), + + 'created_at' => '2025-08-30 00:00:00', + 'updated_at' => '2025-08-30 19:00:00', + ], + [ + 'article' => 'GD-PRDCT-3', + 'title' => 'Some 3', + 'description' => 'Some description 3', + + 'price' => 400, + 'quantity' => 0, + 'currency' => 'USD', + + 'brand' => 'The Best', + + 'images' => json_encode([ + 'https://via.placeholder.com/640x480.png/00ff55?text=s30', + 'https://via.placeholder.com/640x480.png/00ff55?text=s31', + ]), + + 'created_at' => '2025-08-29 00:00:00', + 'updated_at' => '2025-08-29 18:00:00', + ], + ]; + } +} diff --git a/workbench/app/Feeds/Items/SitemapFeedItem.php b/workbench/app/Feeds/Items/SitemapFeedItem.php new file mode 100644 index 0000000..7443cd4 --- /dev/null +++ b/workbench/app/Feeds/Items/SitemapFeedItem.php @@ -0,0 +1,27 @@ + route('products.show', $this->model->article), + + 'lastmod' => $this->model->updated_at->toIso8601String(), + + 'priority' => 0.9, + ]; + } +} diff --git a/workbench/app/Feeds/Items/YandexFeedItem.php b/workbench/app/Feeds/Items/YandexFeedItem.php new file mode 100644 index 0000000..2bcc15e --- /dev/null +++ b/workbench/app/Feeds/Items/YandexFeedItem.php @@ -0,0 +1,46 @@ + $this->model->id, + + 'available' => ! empty($this->model->quantity) ? 'true' : 'false', + + 'type' => 'vendor.model', + ]; + } + + public function toArray(): array + { + return [ + 'url' => route('products.show', $this->model->article), + + 'barcode' => $this->model->article, + 'name' => $this->model->title, + 'description' => $this->model->description, + + 'delivery' => 'true', + 'price' => $this->model->price, + + 'currencyId' => 'RUR', + 'vendor' => $this->model->brand, + + // 'picture' => $this->model->images, + ]; + } +} diff --git a/workbench/app/Feeds/SitemapFeed.php b/workbench/app/Feeds/SitemapFeed.php new file mode 100644 index 0000000..486403c --- /dev/null +++ b/workbench/app/Feeds/SitemapFeed.php @@ -0,0 +1,49 @@ + 'http://www.sitemaps.org/schemas/sitemap/0.9', + 'xmlns:xhtml' => 'http://www.w3.org/1999/xhtml', + 'xmlns:image' => 'http://www.google.com/schemas/sitemap-image/1.1', + 'xmlns:video' => 'http://www.google.com/schemas/sitemap-video/1.1', + 'xmlns:news' => 'http://www.google.com/schemas/sitemap-news/0.9', + ]; + + public function builder(): Builder + { + return Product::query()->where('quantity', '>', 0); + } + + public function root(): ElementData + { + return new ElementData( + $this->name, + $this->attributes + ); + } + + public function filename(): string + { + return 'sitemaps/products.xml'; + } + + public function item(Model $model): FeedItem + { + return new SitemapFeedItem($model); + } +} diff --git a/workbench/app/Feeds/YandexFeed.php b/workbench/app/Feeds/YandexFeed.php new file mode 100644 index 0000000..4860433 --- /dev/null +++ b/workbench/app/Feeds/YandexFeed.php @@ -0,0 +1,67 @@ + + + + $name + $name + $url + $name + $email + + + + + Домашние майки + Велосипедки + Ремни + + XML; + } + + public function footer(): string + { + return "\n\n"; + } + + public function filename(): string + { + return 'yandex.xml'; + } + + public function item(Model $model): FeedItem + { + return new Items\YandexFeedItem($model); + } +} diff --git a/workbench/app/Models/News.php b/workbench/app/Models/News.php index 229f023..f6e36b5 100644 --- a/workbench/app/Models/News.php +++ b/workbench/app/Models/News.php @@ -17,5 +17,6 @@ class News extends Model protected $fillable = [ 'title', 'content', + '', ]; } diff --git a/workbench/app/Models/Product.php b/workbench/app/Models/Product.php new file mode 100644 index 0000000..b8bb4c2 --- /dev/null +++ b/workbench/app/Models/Product.php @@ -0,0 +1,30 @@ + 'test@example.com', +]; diff --git a/workbench/config/feeds.php b/workbench/config/feeds.php index 0311872..69b0c5a 100644 --- a/workbench/config/feeds.php +++ b/workbench/config/feeds.php @@ -4,13 +4,14 @@ use Workbench\App\Feeds\EmptyFeed; use Workbench\App\Feeds\FilledFeed; +use Workbench\App\Feeds\SitemapFeed; +use Workbench\App\Feeds\YandexFeed; return [ 'channels' => [ - // App\Feeds\FooFeed::class => (bool) env('FEED_FOO_ENABLED', true), - // App\Feeds\BarFeed::class => (bool) env('FEED_BAR_ENABLED', true), - // App\Feeds\BazFeed::class => (bool) env('FEED_BAZ_ENABLED', false), - EmptyFeed::class => true, - FilledFeed::class => true, + EmptyFeed::class => true, + FilledFeed::class => true, + SitemapFeed::class => true, + YandexFeed::class => true, ], ]; diff --git a/workbench/database/factories/ProductFactory.php b/workbench/database/factories/ProductFactory.php new file mode 100644 index 0000000..058714a --- /dev/null +++ b/workbench/database/factories/ProductFactory.php @@ -0,0 +1,34 @@ + Str::of(fake()->unique()->password(4, 8))->upper()->prepend('GD-')->toString(), + + 'title' => fake()->unique()->words(4, true), + 'description' => fake()->text(), + 'brand' => fake()->word(), + + 'price' => fake()->numberBetween(100, 1000), + 'quantity' => fake()->numberBetween(0, 10), + 'currency' => fake()->currencyCode(), + + 'images' => json_encode([ + fake()->imageUrl(), + fake()->imageUrl(), + fake()->imageUrl(), + ]), + ]; + } +} diff --git a/workbench/database/migrations/2025_08_30_235243_create_products_table.php b/workbench/database/migrations/2025_08_30_235243_create_products_table.php new file mode 100644 index 0000000..c9db018 --- /dev/null +++ b/workbench/database/migrations/2025_08_30_235243_create_products_table.php @@ -0,0 +1,30 @@ +id(); + + $table->string('article'); + + $table->string('title'); + $table->text('description'); + $table->string('brand'); + + $table->integer('price'); + $table->integer('quantity'); + $table->string('currency'); + + $table->json('images'); + + $table->timestamps(); + }); + } +}; diff --git a/workbench/routes/web.php b/workbench/routes/web.php new file mode 100644 index 0000000..6d0f1df --- /dev/null +++ b/workbench/routes/web.php @@ -0,0 +1,7 @@ +name('products.show') + ->get('products/{product}', static fn (string $product) => $product);