■P255

────────────────
sail test
────────────────


■P256

●app/Services/TweetService.php
────────────────
public function checkOwnTweet(int $userId, int $tweetId): bool
{
    $tweet = Tweet::query()->where('id', $tweetId)->first();
    if (!$tweet) {
        return false;
    }

    return $tweet->user_id === $userId;
}
────────────────


■P257

────────────────
sail artisan make:test Services/TweetServiceTest --unit
────────────────

●tests/Unit/Services/TweetServiceTest.php
────────────────
<?php

namespace Tests\Unit\Services;

use PHPUnit\Framework\TestCase;

class TweetServiceTest extends TestCase
{
    /**
     * A basic unit test example.
     */
    public function test_example(): void
    {
        $this->assertTrue(true);
    }
}
────────────────


■P258

●tests/Unit/Services/TweetServiceTest.php
────────────────
class TweetServiceTest extends TestCase
{
    public function test_check_own_tweet(): void
    {
        $this->assertTrue(true);
    }
}
────────────────

●tests/Unit/Services/TweetServiceTest.php
────────────────
<?php

namespace Tests\Unit\Services;

use App\Services\TweetService;
use PHPUnit\Framework\TestCase;

class TweetServiceTest extends TestCase
{
    /**
     * A basic unit test example.
     */
    public function test_check_own_tweet(): void
    {
        $tweetService = new TweetService(); // TweetServiceのインスタンスを作成
        $this->assertTrue(true);
    }
}
────────────────


■P259

●tests/Unit/Services/TweetServiceTest.php
────────────────
    public function test_check_own_tweet(): void
    {
        $tweetService = new TweetService();

        $result = $tweetService->checkOwnTweet(1, 1);
        $this->assertTrue($result);
    }
────────────────

●tests/Unit/Services/TweetServiceTest.php
────────────────
    public function test_check_own_tweet(): void
    {
        $tweetService = new TweetService();

        $result = $tweetService->checkOwnTweet(1, 1);
        $this->assertTrue($result);

        $result = $tweetService->checkOwnTweet(2, 1);
        $this->assertFalse($result);
    }
────────────────


■P260

●tests/Unit/Services/TweetServiceTest.php
────────────────
<?php

namespace Tests\Unit\Services;

use App\Services\TweetService;
use Mockery;
use PHPUnit\Framework\Attributes\PreserveGlobalState;
use PHPUnit\Framework\Attributes\RunInSeparateProcess;
use PHPUnit\Framework\TestCase;

class TweetServiceTest extends TestCase
{
    /**
     * A basic unit test example.
     */
    #[RunInSeparateProcess]
    #[PreserveGlobalState('disabled')]
    public function test_check_own_tweet(): void
    {
        $tweetService = new TweetService();

        $mock = Mockery::mock('alias:App\Models\Tweet');
        $mock->shouldReceive('query->where->first')->andReturn((object) [
            'id' => 1,
            'user_id' => 1,
        ]);

        $result = $tweetService->checkOwnTweet(1, 1);
        $this->assertTrue($result);

        $result = $tweetService->checkOwnTweet(2, 1);
        $this->assertFalse($result);
    }
}
────────────────


■P261

────────────────
$mock->shouldReceive('query->where->first')->andReturn((object)[
    'id' => 1,
    'user_id' => 1,
]);
────────────────


■P262

────────────────
sail test tests/Unit/Services/TweetServiceTest.php
────────────────


■P263

●tests/Feature/ExampleTest.php
────────────────
<?php

namespace Tests\Feature;

// use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    /**
     * A basic test example.
     */
    public function test_the_application_returns_a_successful_response(): void
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}
────────────────

────────────────
sail test
────────────────


■P264

●app/Http/Controllers/Tweet/DeleteController.php
────────────────
public function __invoke(Request $request, TweetService $tweetService)
{
    $tweetId = (int) $request->route('tweetId');
    if (!$tweetService->checkOwnTweet($request->user()->id, $tweetId)) {
        throw new AccessDeniedHttpException();
    }
    $tweetService->deleteTweet($tweetId);
    return redirect()
        ->route('tweet.index')
        ->with('feedback.success', 'つぶやきを削除しました');
}
────────────────

────────────────
sail artisan make:test Tweet/DeleteTest
────────────────

●tests/Feature/Tweet/DeleteTest.php
────────────────
<?php

namespace Tests\Feature\Tweet;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class DeleteTest extends TestCase
{
    /**
     * A basic feature test example.
     */
    public function test_example(): void
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}
────────────────


■P265

●tests/Feature/Tweet/DeleteTest.php
────────────────
class DeleteTest extends TestCase
{
    /**
     * A basic feature test example.
     */
    public function test_delete_succeeds(): void
    {
        $response = $this->delete('/tweet/1');

        $response->assertRedirect('/tweet');
    }
}
────────────────


■P266

────────────────
sail test tests/Feature/Tweet/DeleteTest.php
────────────────


●tests/Feature/Tweet/DeleteTest.php
────────────────
use Illuminate\Foundation\Testing\RefreshDatabase;

// 略

class DeleteTest extends TestCase
{
    use RefreshDatabase;

    /**
     * A basic feature test example.
     */
    public function test_delete_successed(): void
    {
        $response = $this->delete('/tweet/1');

        $response->assertRedirect('/tweet');
    }
}
────────────────


■P267

●tests/Feature/Tweet/DeleteTest.php
────────────────
<?php

namespace Tests\Feature\Tweet;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class DeleteTest extends TestCase
{
    use RefreshDatabase;

    public function test_delete_successed(): void
    {
        $user = User::factory()->create(); // ユーザーを作成

        $response = $this->delete('/tweet/1');

        $response->assertRedirect('/tweet');
    }
}
────────────────


■P268

●tests/Feature/Tweet/DeleteTest.php
────────────────
use App\Models\Tweet;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class DeleteTest extends TestCase
{
    use RefreshDatabase;

    /**
     * A basic feature test example.
     */
    public function test_delete_successed(): void
    {
        $user = User::factory()->create();

        $tweet = Tweet::factory()->create(['user_id' => $user->id]); // つぶやきを作成

        $response = $this->delete('/tweet/' . $tweet->id); // 作成したつぶやきIDを指定

        $response->assertRedirect('/tweet');
    }
}
────────────────

●tests/Feature/Tweet/DeleteTest.php
────────────────
    public function test_delete_successed(): void
    {
        $user = User::factory()->create();

        $tweet = Tweet::factory()->create(['user_id' => $user->id]); // つぶやきを作成

        $this->actingAs($user); // 指定したユーザーでログインした状態にする

        $response = $this->delete('/tweet/' . $tweet->id); // 作成したつぶやきIDを指定

        $response->assertRedirect('/tweet');
    }
────────────────


■P269

────────────────
sail test tests/Feature/Tweet/DeleteTest.php
────────────────

●MEMOのURL
────────────────
https://pestphp.com/docs/pest-v4-is-here-now-with-browser-testing#content-pest-v4-is-here-now-with-browser-testing
────────────────

────────────────
sail composer require pestphp/pest-plugin-browser:4.3.0 --dev
────────────────


■P270

────────────────
sail npm install playwright@latest
────────────────

────────────────
sail npx playwright install
────────────────

●tests/Pest.php
────────────────
<?php

use Tests\TestCase;

// Pest は RunInSeparateProcess に対応していないため InvalidPestCommand をキャッチした場合は早期リターンする
try {
    \Pest\TestSuite::getInstance();
} catch (\Pest\Exceptions\InvalidPestCommand) {
    return;
}

pest()->extend(Tests\TestCase::class)
    ->in('Browser');
────────────────


■P271

●tests/Browser/LoginTest.php
────────────────
<?php

use App\Models\User;

it('ログインできること', function () {
    $user = User::factory()->create();

    $page = visit('/login')
        ->fill('email', $user->email)
        ->fill('password', 'password')
        ->submit()
        ->assertPathIs('/tweet')
        ->assertSee('つぶやきアプリ');
});
────────────────


■P272

●tests/Browser/LoginTest.php
────────────────
<?php

use App\Models\User;

it('ログインできること', function () {
    $user = User::factory()->create(); // テスト用のユーザーを作成する

    $page = visit('/login')
        ->fill('email', $user->email)
        ->fill('password', 'password')
        ->submit()
        ->assertPathIs('/tweet')
        ->assertSee('つぶやきアプリ');
});
────────────────

●tests/Browser/LoginTest.php
────────────────
<?php

use App\Models\User;

it('ログインできること', function () {
    $user = User::factory()->create();

    $page = visit('/login')
        ->fill('email', $user->email)
        ->fill('password', 'password')
        ->submit()
        ->assertPathIs('/tweet')
        ->assertSee('つぶやきアプリ');
});
────────────────


■P273

●tests/Browser/LoginTest.php
────────────────
<?php

use App\Models\User;

it('ログインできること', function () {
    $user = User::factory()->create();

    $page = visit('/login')
        ->fill('email', $user->email) // メールアドレスを入力する
        ->fill('password', 'password')
        ->submit()
        ->assertPathIs('/tweet')
        ->assertSee('つぶやきアプリ');
});
────────────────


■P274

●tests/Browser/LoginTest.php
────────────────
<?php

use App\Models\User;

it('ログインできること', function () {
    $user = User::factory()->create();

    $page = visit('/login')
        ->fill('email', $user->email)
        ->fill('password', 'password') // パスワードを入力する
        ->submit()
        ->assertPathIs('/tweet')
        ->assertSee('つぶやきアプリ');
});
────────────────

●tests/Browser/LoginTest.php
────────────────
<?php

use App\Models\User;

it('ログインできること', function () {
    $user = User::factory()->create();

    $page = visit('/login')
        ->fill('email', $user->email)
        ->fill('password', 'password')
        ->submit() // フォームを送信する
        ->assertPathIs('/tweet')
        ->assertSee('つぶやきアプリ');
});
────────────────


■P275

●MEMOのURL
────────────────
https://pestphp.com/docs/browser-testing
────────────────

●tests/Browser/LoginTest.php
────────────────
<?php

use App\Models\User;

it('ログインできること', function () {
    $user = User::factory()->create();

    $page = visit('/login')
        ->fill('email', $user->email)
        ->fill('password', 'password')
        ->submit()
        ->assertPathIs('/tweet') // /tweetに遷移したことを確認する
        ->assertSee('つぶやきアプリ');
});
────────────────

●tests/Browser/LoginTest.php
────────────────
<?php

use App\Models\User;

it('ログインできること', function () {
    $user = User::factory()->create();

    $page = visit('/login')
        ->fill('email', $user->email)
        ->fill('password', 'password')
        ->submit()
        ->assertPathIs('/tweet')
        ->assertSee('つぶやきアプリ'); // ページ内に「つぶやきアプリ」が表示されていることの確認
});
────────────────


■P276

────────────────
sail bin pest tests/Browser/LoginTest.php
────────────────
