diff --git a/.gitea/workflows/demo.yaml b/.gitea/workflows/demo.yaml index e14c37c..7edbde4 100644 --- a/.gitea/workflows/demo.yaml +++ b/.gitea/workflows/demo.yaml @@ -12,7 +12,7 @@ jobs: - name: Check out repository code uses: actions/checkout@v3 - run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner." - - run: echo "🖥️ The workflow is now ready to test your code on the runner." + - run: echo "The workflow is now ready to test your code on the runner." - name: List files in the repository run: | ls ${{ gitea.workspace }} diff --git a/README.md b/README.md index 0f04337..dec1173 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,5 @@ ``` The main Eatvio web project ``` + +see [eatvio-infra](http://gitea.office.local:3000/eatvio/eatvio-infra) diff --git a/app/Http/Controllers/PlanController.php b/app/Http/Controllers/PlanController.php index 474a66f..6484d94 100644 --- a/app/Http/Controllers/PlanController.php +++ b/app/Http/Controllers/PlanController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers; use App\Models\Plan; use App\Models\User; use Illuminate\Http\Request; +use App\Models\PlanComment; class PlanController extends Controller { @@ -65,16 +66,16 @@ class PlanController extends Controller // $options1 = $this->unserializeOptions($plan->packet1_options); // $options2 = $this->unserializeOptions($plan->packet2_options); // $options3 = $this->unserializeOptions($plan->packet2_options); - $options1 = $plan->packet1_options; - $options2 = $plan->packet2_options; - $options3 = $plan->packet2_options; + // $options1 = $plan->packet1_options; + // $options2 = $plan->packet2_options; + // $options3 = $plan->packet2_options; return view('plan/show', [ 'plan' => $plan, - 'options1' => $options1, - 'options2' => $options2, - 'options3' => $options3 + // 'options1' => $options1, + // 'options2' => $options2, + // 'options3' => $options3, ] ); } diff --git a/app/Livewire/Plan/Accordion.php b/app/Livewire/Plan/Accordion.php new file mode 100644 index 0000000..06dad1b --- /dev/null +++ b/app/Livewire/Plan/Accordion.php @@ -0,0 +1,40 @@ + false, 'options2' => false, 'options3' => false]; + public $options1; + public $options2; + public $options3; + + public function mount(Plan $plan): void + { + $this->plan = $plan; + $this->options1 = $plan->packet1_options; + $this->options2 = $plan->packet2_options; + $this->options3 = $plan->packet3_options; + + } + + public function render() + { + return view('livewire.plan.accordion'); + } + + public function toggleAccordionState($optionName) + { + $this->accordionState[$optionName] = !$this->accordionState[$optionName]; + + + // 1. Если у нас 1 true все остальные делать false(чтобы закрывать остальные вкладки у которых не true) + // a. у нас есть ключ у которого будет true + // b. проходим по всем ключам accordionState и все кроме true делаем false + array_map(fn($key) => $key === $optionName ?: $this->accordionState[$key] = false, array_keys($this->accordionState)); + } +} diff --git a/app/Livewire/Plan/Comment/Create.php b/app/Livewire/Plan/Comment/Create.php index 26b029b..cf89e2c 100644 --- a/app/Livewire/Plan/Comment/Create.php +++ b/app/Livewire/Plan/Comment/Create.php @@ -6,6 +6,7 @@ use Livewire\Component; use App\Models\Plan; use App\Models\PlanComment; use App\Models\User; +use Livewire\Attributes\Validate; class Create extends Component { @@ -21,6 +22,11 @@ class Create extends Component public function save() { + $this->validate([ + 'body' => 'required|min:10', + 'grade' => 'required', + ]); + $comment = new PlanComment(); $comment->grade = $this->grade; $comment->body = $this->body; diff --git a/app/Livewire/Plan/Comment/Show.php b/app/Livewire/Plan/Comment/Show.php index 3c54559..066fc25 100644 --- a/app/Livewire/Plan/Comment/Show.php +++ b/app/Livewire/Plan/Comment/Show.php @@ -8,6 +8,7 @@ use App\Models\Plan; class Show extends Component { public Plan $plan; + public array $tabpanelState = ['positive' => 'positive', 'negative' => false]; protected $listeners = ['commentAdded' => '$refresh']; @@ -15,4 +16,9 @@ class Show extends Component { return view('livewire.plan.comment.show'); } + + public function toggleTabpanelState($tabpanelName) + { + array_map(fn($key) => $key === $tabpanelName ? $this->tabpanelState[$tabpanelName] = $tabpanelName : $this->tabpanelState[$key] = false, array_keys($this->tabpanelState)); + } } diff --git a/app/Livewire/Recipe/Edit.php b/app/Livewire/Recipe/Edit.php index d6baf0d..bb43464 100644 --- a/app/Livewire/Recipe/Edit.php +++ b/app/Livewire/Recipe/Edit.php @@ -24,6 +24,9 @@ class Edit extends Component public $description = ""; public $steps = [['image' => '', 'description' => '']]; public $ingredients = [['name' => '', 'portion' => '']]; + public $ingredients_name = ""; + public $ingredients_portion = ""; + public $ingredients_unit = "gr"; protected $listeners = ['stepRemoved' => '$refresh', 'parentComponentTagAdded', 'parentComponentTagRemoved']; @@ -86,9 +89,15 @@ class Edit extends Component public function removeStep($i) { + if (is_array($this->steps)) { + $steps = $this->steps; + } + else { + $steps = $this->steps->toArray(); + } $searchKey = $i - 1; $newSteps = array_filter( - $this->steps, + $steps, function ($key) use ($searchKey) { return $key != $searchKey; }, @@ -141,7 +150,6 @@ class Edit extends Component public function publish() { - dd($this->steps); $this->validate(); $recipe = $this->recipe; diff --git a/app/Models/Plan.php b/app/Models/Plan.php index 20a25d3..7e168c9 100644 --- a/app/Models/Plan.php +++ b/app/Models/Plan.php @@ -1,16 +1,17 @@ 'array', ]; - protected $presenter = PlanPresenter::class; - public function author() { return $this->belongsToMany(User::class, 'plan_author', 'plan_id', 'user_id'); @@ -63,12 +61,12 @@ class Plan extends Model implements Viewable { $result = []; for ($i = 1; $i <= $this->packets_count; $i++) { - $key = "packet" . $i . "_options"; + $key = 'packet' . $i . '_options'; // $data = $this->unserializeOptionsObj($this->$key); $data = $this->$key; if (!is_null($data)) { - $result = array_merge($result, data_get($data, "items", [])); + $result = array_merge($result, data_get($data, 'items', [])); } } @@ -81,7 +79,7 @@ class Plan extends Model implements Viewable $data = $this->type; return new Attribute( - get: fn () => array_keys($data), + get: fn() => array_keys($data), ); } @@ -89,18 +87,18 @@ class Plan extends Model implements Viewable { $result = 0; for ($i = 1; $i <= $this->packets_count; $i++) { - $key = "packet" . $i . "_options"; + $key = 'packet' . $i . '_options'; // dd($this->$key); // $data = $this->unserializeOptionsObj($this->$key); $data = $this->$key; if (!is_null($data)) { - $curPrice = (int)data_get($data, "price", 0); - $result = $curPrice > $result ? $curPrice : $result ; + $curPrice = (int) data_get($data, 'price', 0); + $result = $curPrice > $result ? $curPrice : $result; } } return new Attribute( - get: fn () => $result, + get: fn() => $result, ); } @@ -128,4 +126,14 @@ class Plan extends Model implements Viewable } return json_decode(stripslashes($str), true); } + + public function scopeByNegative(Builder $query) + { + return static::comments()->where('grade', '<=', '3'); + } + + public function scopeByPositive(Builder $query) + { + return static::comments()->where('grade', '>', '3'); + } } diff --git a/database/factories/PlanCommentFactory.php b/database/factories/PlanCommentFactory.php new file mode 100755 index 0000000..eb18786 --- /dev/null +++ b/database/factories/PlanCommentFactory.php @@ -0,0 +1,28 @@ + + */ +class PlanCommentFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + + return [ + 'grade' => $this->faker->randomDigit(), + 'body' => $this->faker->text(), + ]; + + } +} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index a8222ee..a346b78 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -16,6 +16,7 @@ class DatabaseSeeder extends Seeder { $this->call(PlanSeeder::class); $this->call(UserSeeder::class); + $this->call(RecipeSeeder::class); // \App\Models\User::factory(10)->create(); } } diff --git a/database/seeders/PlanCommentSeeder.php b/database/seeders/PlanCommentSeeder.php new file mode 100755 index 0000000..8f4c844 --- /dev/null +++ b/database/seeders/PlanCommentSeeder.php @@ -0,0 +1,38 @@ + 0 && Plan::count() > 0) { + $comments = PlanComment::factory()->count(5)->make(); + + $comments->each(function ($comment) { + $comment->author()->associate( + User::inRandomOrder() + ->first() + ->id + ); + + $comment->plan()->associate( + Plan::inRandomOrder() + ->first() + ->id + ); + + $comment->saveOrFail(); + }); + } + } +} diff --git a/database/seeders/RecipeSeeder.php b/database/seeders/RecipeSeeder.php new file mode 100644 index 0000000..5120977 --- /dev/null +++ b/database/seeders/RecipeSeeder.php @@ -0,0 +1,72 @@ +image = $this->downloadRandomImage(); + $recipe->state = 'active'; + $recipe->type = $faker->randomElement(['first_meals', 'second_meals', 'salads', 'snacks', 'drinks', 'other']); + $recipe->title = $faker->sentence(5); + $recipe->video_url = $faker->url; + $recipe->cooking_time = $faker->randomElement([10,20,30,60,120,14400]); + $recipe->description = $faker->text(200); + $recipe->steps = [ + ['image' => $this->downloadRandomImage(), 'description' => $faker->text(100)], + ['image' => $this->downloadRandomImage(), 'description' => $faker->text(100)], + ['image' => $this->downloadRandomImage(), 'description' => $faker->text(100)] + ]; + $recipe->ingredients = [ + ['name' => $faker->word, 'portion' => $faker->numberBetween(1, 20), 'unit' => $faker->randomElement(['teespoon', 'tablespoon', 'ml', 'pcs', 'clove', 'to_taste'])], + ['name' => $faker->word, 'portion' => $faker->numberBetween(1, 20), 'unit' => $faker->randomElement(['teespoon', 'tablespoon', 'ml', 'pcs', 'clove', 'to_taste'])], + ['name' => $faker->word, 'portion' => $faker->numberBetween(1, 20), 'unit' => $faker->randomElement(['teespoon', 'tablespoon', 'ml', 'pcs', 'clove', 'to_taste'])], + ]; + $recipe->save(); + for ($j = 0; $j < 10; $j++) { + $comment = new RecipeComment(); + $comment->user_id = User::inRandomOrder()->first()->id; + $comment->recipe_id = $recipe->id; + $comment->grade = $faker->randomElement([1,2,3,4,5]); + $comment->body = $faker->text(100); + $comment->save(); + } + User::inRandomOrder()->first()->author_of_recipe()->attach($recipe->id); + } + + + } + public function downloadRandomImage(): string + { + $faker = FakerFactory::create(); + $url = $faker->imageUrl(640, 480, 'food', true); + $contents = file_get_contents($url); + $dir_path = storage_path('app/public/recipe'); + $path = 'recipe/' . uniqid() . '.jpg'; + if (!file_exists( $dir_path)) { + mkdir( $dir_path, 0777, true); + } + file_put_contents(storage_path('app/public/' . $path), $contents); + + return $path; + } +} diff --git a/resources/views/auth/confirm-password.blade.php b/resources/views/auth/confirm-password.blade.php index ccc4b28..33905ff 100644 --- a/resources/views/auth/confirm-password.blade.php +++ b/resources/views/auth/confirm-password.blade.php @@ -1,4 +1,7 @@ + @push('css_head') + + @endpush diff --git a/resources/views/auth/forgot-password.blade.php b/resources/views/auth/forgot-password.blade.php index 0097654..aba7922 100644 --- a/resources/views/auth/forgot-password.blade.php +++ b/resources/views/auth/forgot-password.blade.php @@ -1,4 +1,7 @@ + @push('css_head') + + @endpush diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 0c5902d..991b1ef 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -1,4 +1,8 @@ + + @push('css_head') + + @endpush diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index 8a5f240..6681119 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -1,4 +1,7 @@ + @push('css_head') + + @endpush diff --git a/resources/views/auth/reset-password.blade.php b/resources/views/auth/reset-password.blade.php index 5991e3e..daeee33 100644 --- a/resources/views/auth/reset-password.blade.php +++ b/resources/views/auth/reset-password.blade.php @@ -1,4 +1,7 @@ + @push('css_head') + + @endpush diff --git a/resources/views/auth/two-factor-challenge.blade.php b/resources/views/auth/two-factor-challenge.blade.php index eec9264..da87857 100644 --- a/resources/views/auth/two-factor-challenge.blade.php +++ b/resources/views/auth/two-factor-challenge.blade.php @@ -1,4 +1,7 @@ + @push('css_head') + + @endpush diff --git a/resources/views/auth/verify-email.blade.php b/resources/views/auth/verify-email.blade.php index 59669c6..0ec4cbc 100644 --- a/resources/views/auth/verify-email.blade.php +++ b/resources/views/auth/verify-email.blade.php @@ -1,4 +1,7 @@ + @push('css_head') + + @endpush diff --git a/resources/views/layouts/eatvio.blade.php b/resources/views/layouts/eatvio.blade.php index f70b4c4..309e77c 100644 --- a/resources/views/layouts/eatvio.blade.php +++ b/resources/views/layouts/eatvio.blade.php @@ -145,3 +145,4 @@ $isDiary = Str::of($curUrl)->test('/\/diary/'); + diff --git a/resources/views/layouts/guest.blade.php b/resources/views/layouts/guest.blade.php index fa10db7..1f7f378 100644 --- a/resources/views/layouts/guest.blade.php +++ b/resources/views/layouts/guest.blade.php @@ -16,6 +16,7 @@ + @stack('css_head') @livewireStyles diff --git a/resources/views/livewire/plan/accordion.blade.php b/resources/views/livewire/plan/accordion.blade.php new file mode 100644 index 0000000..2626ac2 --- /dev/null +++ b/resources/views/livewire/plan/accordion.blade.php @@ -0,0 +1,99 @@ +
+
+ +
!$accordionState['options1'], 'display: block' => $accordionState['options1']])> +
+ {{ $options1['description'] ?? '' }} +
+ + @isset($options1['items']) + @foreach ($options1['items'] as $item) +
    +
  • + {{ $item }} + + {{-- - --}} +
  • +
+ @endforeach + @endisset + +
+
+ + @if ($plan->packets_count == 3) +
+ +
!$accordionState['options2'], 'display: block' => $accordionState['options2']])> +
+ {{ $options2['description'] ?? '' }} +
+ + @isset($options2['items']) + @foreach ($options2['items'] as $item) +
    +
  • + {{ $item }} + + {{-- - --}} +
  • +
+ @endforeach + @endisset + +
+
+ +
+ +
!$accordionState['options3'], 'display: block' => $accordionState['options3']])> +
+ {{ $options3['description'] ?? '' }} +
+ + @isset($options3['items']) + @foreach ($options3['items'] as $item) +
    +
  • + {{ $item }} + + {{-- - --}} +
  • +
+ @endforeach + @endisset + +
+
+ @endif +
diff --git a/resources/views/livewire/plan/comment/create.blade.php b/resources/views/livewire/plan/comment/create.blade.php index 8873d7e..08bfe13 100644 --- a/resources/views/livewire/plan/comment/create.blade.php +++ b/resources/views/livewire/plan/comment/create.blade.php @@ -1,24 +1,18 @@ -
-
- - + diff --git a/resources/views/livewire/plan/comment/show.blade.php b/resources/views/livewire/plan/comment/show.blade.php index fd83b28..d952cbc 100644 --- a/resources/views/livewire/plan/comment/show.blade.php +++ b/resources/views/livewire/plan/comment/show.blade.php @@ -1,59 +1,89 @@
@php - $positivComments = $plan->comments()->where('grade', '>', '3'); - $negativeComments = $plan->comments()->where('grade', '<=', '3'); - $positiveCommmentsCount = $positivComments->count(); - $negativeCommentsCount = $negativeComments->count(); - @endphp - -
-
- @foreach($positivComments->get() as $comment) -
-
- -
- {{ $comment->author->name }} - {{ $comment->body }} + $positivComments = $plan->byPositive(); + $negativeComments = $plan->byNegative(); + + $positiveCommmentsCount = $positivComments->count(); + + $negativeCommentsCount = $negativeComments->count(); + + @endphp + +
+
+ + +
+ +
$tabpanelState['negative'] + ]) role="tabpanel" id="tabpanel-1" tabindex="0" aria-labelledby="tab-1"> + @foreach ($positivComments->get() as $comment) +
+
+
+ user
-
-
-
- - {{ $comment->grade }} +
+
+ {{ $comment->author->name }} +
+
+ {{ $comment->body }} +
+
+
+
+ {{ $plan->name }} +
+
+ {{ $comment->grade }} +
+ {{-- @livewire('plan.comment.upvote', ['comment' => $comment]) --}}
- @livewire('plan.comment.upvote', ['comment' => $comment])
@endforeach
-
- @foreach($negativeComments->get() as $comment) -
-
- -
- {{ $comment->author->name }} - {{ $comment->body }} + + +
$tabpanelState['positive'] + ]) role="tabpanel" id="tabpanel-1" tabindex="0" aria-labelledby="tab-1"> + @foreach ($negativeComments->get() as $comment) +
+
+
+ user
-
-
-
- - {{ $comment->grade }} +
+
+ {{ $comment->author->name }} +
+
+ {{ $comment->body }} +
+
+
+
+ {{ $plan->name }} +
+
+ {{ $comment->grade }} +
+ {{-- @livewire('plan.comment.upvote', ['comment' => $comment]) --}}
- @livewire('plan.comment.upvote', ['comment' => $comment])
@endforeach
+
+
diff --git a/resources/views/livewire/plan/create.blade.php b/resources/views/livewire/plan/create.blade.php index 6c1cad7..ad334b1 100644 --- a/resources/views/livewire/plan/create.blade.php +++ b/resources/views/livewire/plan/create.blade.php @@ -373,8 +373,6 @@
- -
@@ -652,8 +650,8 @@ @endisset
-
@@ -689,20 +687,7 @@ class="diet__btn btn btn-primary">Опубликовать
+
@endif - -
-
- - -
- -
-
-
diff --git a/resources/views/livewire/recipe/edit.blade.php b/resources/views/livewire/recipe/edit.blade.php index f5578c3..13fee5f 100644 --- a/resources/views/livewire/recipe/edit.blade.php +++ b/resources/views/livewire/recipe/edit.blade.php @@ -25,180 +25,141 @@
-
+
-
{{ __('recipe.picture') }}
- + @error('image') {{ $message }} @enderror
-
-
- Тип записи +
+
+ Тип записи +
+
+ + +
-
- - +
+
+
+
+
{{ __('recipe.cooking_time') }}
+ +
-
+
+
+
{{ __('recipe.record_state') }}
+ +
-
-
-
-
{{ __('recipe.cooking_time') }}
- +
+
+
+ +
+
+ + + + + + + + + + +
+ +
+
+
+ -
-
- - - - - Рецепты - -
- - - - {{ $recipeViewsCount }} - - - - @livewire('recipe.like-count', ['recipe' => $recipe]) - - - - {{ $recipe->comments_count }} -
-
- {{ $author['name'] }} - -
-
-
-
-
-
- -
-
-
-
{{ $recipe->title }}
-
- - - {{ __('recipe.t' . $recipe->cooking_time . "m") }} - - - {{ $recipe->steps->count() }} этапов -
- -
- - {!! $recipe->description !!} - -
-
-
- @if (strlen(trim($recipe->video_url)) > 4) - - Посмотреть рецепт на YouTube - - - - - @endif -
-
- -
- -
-
-
продукты:
-
    - @foreach($recipe->ingredients as $ingredient) - @php - $localizedUnit = (isset($ingredient['unit']) && mb_strlen($ingredient['unit']) > 1) - ? $ingredient['unit'] - : 'gr'; - @endphp - @if(mb_strlen($ingredient['name']) > 1) -
  • {{ $ingredient['name'] }} - {{ $ingredient['portion'] }} {{ __('recipe.' . $localizedUnit ) }}
  • - @endif - @endforeach -
-
-
-
Теги:
-
- @foreach($recipe->tags->unique() as $curTag) - {{ $curTag->name }} - @endforeach -
-
-
- -
- - - - - - Комментировать - - - @livewire('recipe.like', ['recipe' => $recipe]) - - - - - - Поделится - - -
-
-
- -
-
Пошаговый фото рецепт - {{ $recipe->title }}
-
- @foreach($recipe->steps as $step) -
-
- @if(isset($step['image']) && is_string($step['image']) && strlen($step["image"]) > 4) - - @endif -
-
- - {!! $step['description'] !!} - -
-
- @endforeach -
-
- -
- @livewire('recipe.comment.show', ['recipe' => $recipe]) -
-
- @livewire('recipe.comment.create', ['recipe' => $recipe, 'user' => Auth::user()]) -
-
-@endsection -@push('jq_scripts') - - -@endpush + @endsection + @push('jq_scripts') + + + @endpush diff --git a/tests/Feature/Recipe/EditTest.php b/tests/Feature/Recipe/EditTest.php new file mode 100644 index 0000000..8978f9c --- /dev/null +++ b/tests/Feature/Recipe/EditTest.php @@ -0,0 +1,105 @@ +create(); + $recipe = Recipe::factory()->create([ + 'steps' => [], + 'ingredients' => [], + ]); + $tag1 = Tag::factory()->create(); + $tag2 = Tag::factory()->create(); + + $title = $faker->sentence(3); + $description = $faker->paragraph(2); + $cooking_time = $faker->numberBetween(10, 120); + $type = $faker->randomElement(['Main Dish', 'Dessert', 'Appetizer']); + $video_url = $faker->url; + $image = UploadedFile::fake()->image('new_image.jpg'); + $ingredients_names = [$faker->word, $faker->word, $faker->word]; + $ingredients_portions = [$faker->numberBetween(1, 500), $faker->numberBetween(1, 500), $faker->numberBetween(1, 500)]; + $ingredient_units = [$faker->randomElement(['gr', 'ml', 'pcs']), $faker->randomElement(['gr', 'ml', 'pcs']), $faker->randomElement(['gr', 'ml', 'pcs'])]; + + Livewire::actingAs($user) + ->test('recipe.edit', ['recipe' => $recipe]) + ->set('title', $title) + ->set('description', $description) + ->set('cooking_time', $cooking_time) + ->set('type', $type) + ->set('video_url', $video_url) + ->set('image', $image) + ->set('tags', [$tag1->id, $tag2->id]) + ->call('addIngredient') + ->set('ingredients_name.0', $ingredients_names[0]) + ->set('ingredients_portion.0', $ingredients_portions[0]) + ->set('ingredients_unit.0', $ingredient_units[0]) + ->call('addIngredient') + ->set('ingredients_name.1', $ingredients_names[1]) + ->set('ingredients_portion.1', $ingredients_portions[1]) + ->set('ingredients_unit.1', $ingredient_units[1]) + ->call('addIngredient') + ->set('ingredients_name.2', $ingredients_names[2]) + ->set('ingredients_portion.2', $ingredients_portions[2]) + ->set('ingredients_unit.2', $ingredient_units[2]) + ->call('addStep') + ->set('steps.0.description', $faker->paragraph) + ->set('steps.0.image', UploadedFile::fake()->image('new_step_image0.jpg')) + ->call('addStep') + ->set('steps.1.description', $faker->paragraph) + ->set('steps.1.image', UploadedFile::fake()->image('new_step_image1.jpg')) + ->call('addStep') + ->set('steps.2.description', $faker->paragraph) + ->set('steps.2.image', UploadedFile::fake()->image('new_step_image2.jpg')) + ->call('publish'); + + $this->assertDatabaseHas('recipes', [ + 'title' => $title, + 'description' => $description, + 'cooking_time' => $cooking_time, + 'type' => $type, + 'video_url' => $video_url, + 'image' => $image, + 'ingredients_name.0' => $ingredients_names[0], + 'ingredients_portion.0' => $ingredients_portions[0], + 'ingredients_unit.0' => $ingredient_units[0], + 'ingredients_name.1' => $ingredients_names[1], + 'ingredients_portion.1' => $ingredients_portions[1], + 'ingredients_unit.1' => $ingredient_units[1], + 'ingredients_name.2' => $ingredients_names[2], + 'ingredients_portion.2' => $ingredients_portions[2], + 'ingredients_unit.2' => $ingredient_units[2], + ]); + + $this->assertDatabaseHas('tags', [ + 'id' => $tag1->id, + ]); + $this->assertDatabaseHas('tags', [ + 'id' => $tag2->id, + ]); + + Storage::disk('public')->assertExists('recipes/new_image.jpg'); + Storage::disk('public')->assertExists('steps/new_step_image0.jpg'); + Storage::disk('public')->assertExists('steps/new_step_image1.jpg'); + Storage::disk('public')->assertExists('steps/new_step_image2.jpg'); + } +}