TestCase.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <?php
  2. namespace Longyi\Core\Tests;
  3. use Illuminate\Support\Facades\DB;
  4. use Illuminate\Support\Facades\Schema;
  5. use Tests\TestCase as BaseTestCase;
  6. use Webkul\Attribute\Models\Attribute;
  7. use Webkul\Category\Models\Category;
  8. use Webkul\Core\Models\Channel;
  9. use Webkul\Product\Models\Product;
  10. use Webkul\Product\Models\ProductAttributeValue;
  11. abstract class TestCase extends BaseTestCase
  12. {
  13. protected function setUp(): void
  14. {
  15. parent::setUp();
  16. if (! Schema::hasTable('products') || ! Schema::hasTable('attribute_families')) {
  17. $this->markTestSkipped('Catalog tables are missing.');
  18. }
  19. }
  20. protected function seedRequiredData(): void
  21. {
  22. try {
  23. if (! Category::query()->exists()) {
  24. Category::factory()->create([
  25. 'parent_id' => null,
  26. ]);
  27. }
  28. if (! Channel::query()->exists()) {
  29. Channel::factory()->create();
  30. }
  31. } catch (\Exception $e) {
  32. $this->markTestSkipped('Test database not properly configured: '.$e->getMessage());
  33. }
  34. }
  35. protected function createSimpleProduct(array $overrides = []): Product
  36. {
  37. $this->seedRequiredData();
  38. $attributeFamilyId = (int) (DB::table('attribute_families')->value('id') ?? 0);
  39. if ($attributeFamilyId === 0) {
  40. $this->markTestSkipped('Run Bagisto seeders for attribute_families.');
  41. }
  42. $product = Product::factory()->create([
  43. 'type' => 'simple',
  44. 'attribute_family_id' => $attributeFamilyId,
  45. ...$overrides,
  46. ]);
  47. $this->upsertProductAttributeValue($product->id, 'name', 'Test '.$product->sku);
  48. $this->upsertProductAttributeValue($product->id, 'url_key', strtolower($product->sku));
  49. $this->upsertProductAttributeValue($product->id, 'status', 1, null, 'default');
  50. $this->upsertProductAttributeValue($product->id, 'price', 10.0, null, null);
  51. return $product;
  52. }
  53. protected function upsertProductAttributeValue(
  54. int $productId,
  55. string $attributeCode,
  56. mixed $value,
  57. ?string $locale = 'en',
  58. ?string $channel = null
  59. ): void {
  60. $attribute = Attribute::query()->where('code', $attributeCode)->first();
  61. if (! $attribute) {
  62. $this->markTestSkipped(sprintf('Required attribute "%s" not found. Run Bagisto seeders for attributes.', $attributeCode));
  63. }
  64. $type = (string) ($attribute->type ?? 'text');
  65. $field = ProductAttributeValue::$attributeTypeFields[$type] ?? 'text_value';
  66. $payload = [
  67. 'product_id' => $productId,
  68. 'attribute_id' => (int) $attribute->id,
  69. 'locale' => $attribute->value_per_locale ? $locale : null,
  70. 'channel' => $attribute->value_per_channel ? ($channel ?? 'default') : null,
  71. 'text_value' => null,
  72. 'boolean_value' => null,
  73. 'integer_value' => null,
  74. 'float_value' => null,
  75. 'datetime_value' => null,
  76. 'date_value' => null,
  77. 'json_value' => null,
  78. ];
  79. $payload[$field] = $field === 'boolean_value'
  80. ? (bool) $value
  81. : ($field === 'float_value' ? (float) $value : $value);
  82. $payload['unique_id'] = implode('|', array_filter([
  83. $payload['channel'],
  84. $payload['locale'],
  85. $productId,
  86. (int) $attribute->id,
  87. ]));
  88. ProductAttributeValue::query()->updateOrCreate(
  89. [
  90. 'product_id' => $productId,
  91. 'attribute_id' => (int) $attribute->id,
  92. 'locale' => $payload['locale'],
  93. 'channel' => $payload['channel'],
  94. ],
  95. $payload
  96. );
  97. }
  98. protected function attributeText(int $productId, string $code): ?string
  99. {
  100. $attribute = Attribute::query()->where('code', $code)->first();
  101. if (! $attribute) {
  102. return null;
  103. }
  104. $field = ProductAttributeValue::$attributeTypeFields[$attribute->type] ?? 'text_value';
  105. $row = ProductAttributeValue::query()
  106. ->where('product_id', $productId)
  107. ->where('attribute_id', $attribute->id)
  108. ->orderByDesc('id')
  109. ->first();
  110. if (! $row) {
  111. return null;
  112. }
  113. $value = $row->{$field};
  114. return $value === null ? null : (string) $value;
  115. }
  116. protected function ensureInventory(Product $product, int $qty = 50): int
  117. {
  118. $inventorySourceId = (int) (DB::table('inventory_sources')->value('id') ?? 0);
  119. if (! $inventorySourceId) {
  120. $this->markTestSkipped('No inventory_sources found. Run Bagisto seeders for inventory sources.');
  121. }
  122. DB::table('product_inventories')->updateOrInsert(
  123. [
  124. 'product_id' => $product->id,
  125. 'inventory_source_id' => $inventorySourceId,
  126. 'vendor_id' => 0,
  127. ],
  128. ['qty' => $qty]
  129. );
  130. return $inventorySourceId;
  131. }
  132. protected function createNamedCategory(string $name, string $locale = 'en'): Category
  133. {
  134. $category = Category::factory()->create([
  135. 'parent_id' => null,
  136. ]);
  137. DB::table('category_translations')->updateOrInsert(
  138. [
  139. 'category_id' => $category->id,
  140. 'locale' => $locale,
  141. ],
  142. [
  143. 'name' => $name,
  144. 'slug' => strtolower(str_replace(' ', '-', $name)).'-'.$category->id,
  145. 'url_path' => strtolower(str_replace(' ', '-', $name)).'-'.$category->id,
  146. 'description' => $name,
  147. ]
  148. );
  149. return $category->fresh();
  150. }
  151. }