第3章 タスクの更新と完了

03.ビューの実装

ビューファイルの修正

今回は、すでにある「詳細画面」を更新できるように修正しよう。 具体的に言えば、Formを使うようにする。

LaravelでFormを扱う場合、Laravel CollectiveForms & HTMLをインストールしておくと Form周りの記載をやりやすくなる。

https://laravelcollective.com/docs/master/html

$ composer require "laravelcollective/html":"^5.4.0"
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing laravelcollective/html (v5.5.4): Loading from cache
Writing lock file
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
Discovered Package: fideloper/proxy
Discovered Package: laravel/dusk
Discovered Package: laravel/tinker
Discovered Package: laravelcollective/html
Package manifest generated successfully.

次に、config/app.phpを下記のように修正する。





 

 
 


()
        /*
         * Package Service Providers...
         */
        Collective\Html\HtmlServiceProvider::class,
()
        'Form' => Collective\Html\FormFacade::class,
        'Html' => Collective\Html\HtmlFacade::class,
()

170行目、230行目〜231行目に、それぞれ上記のように追加する。 これで、ビューファイル内でForms & HTMLの機能を呼び出せるようになる。

では、resources/views/tasks/detail.blade.phpの修正を行なってみよう。






















 









 
 



 
 






<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.3.1.min.js" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
            integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
            crossorigin="anonymous"></script>

    <title>Tasks</title>
</head>
<body>
<div class="container">
    <h2>Tasks Detail</h2>
    <div class="row">
        <div class="col-md-offset-2 col-md-8">
            {!! Form::open(['action' => ['TaskController@update', $task->id], 'method' => 'put']) !!}
            <table class="table table-hover">
                <thead>
                <tr>
                    <td>タイトル</td>
                    <td>実行済み</td>
                </tr>
                </thead>
                <tbody>
                <tr>
                    <td>{{ Form::text('title', $task->title, ['id' => 'title', 'class' => 'form-control']) }}</td>
                    <td>{{ Form::checkbox('executed', 'on', $task->executed) }}</td>
                </tr>
                </tbody>
            </table>
            {{ Form::submit('更新', ['class' => 'btn btn-primary']) }}
            {!! Form::close() !!}
        </div>
    </div>
</div>
</body>
</html>

22行目と38行目で、Formの開始と終了のタグを生成している。 特に開始の方は、Submit時の送信パスをURLだけでなくLaravelの内部表現でも書けるのでかなり使いやすい。

今回は、web.php内で定義しているController@methodの形式とした。

32行目〜33行目が、データ表示部分だ。ここをForm::text()Form::checkbox()に置き換えている。 特に33行目の方は、元々は表示時のオン/オフの処理で三項演算子を使った書き分けをしていたが、 このように引数に渡すことでうまいこと対応してくれる。

ビューのテスト作成と実行

では、今回もテストコードを実装しよう。

ここでテストすべきは、「表示内容」と「Formの処理」だ。

tests/Browser/TaskDetailTest.phpを下記のようにする。

























 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 




<?php

namespace Tests\Browser;

use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Illuminate\Foundation\Testing\DatabaseMigrations;

class TaskDetailTest extends DuskTestCase
{
    /**
     * Task Detail Test.
     *
     * @throws \Throwable
     */
    public function testShowDetail()
    {
        $this->browse(function (Browser $browser) {
            $browser->visit('/tasks/2')
                ->assertSee('テストタスク')
                ->screenshot("task_detail");
        });
    }

    /**
     * Task Post Test.
     *
     * @throws \Throwable
     */
    public function testPost()
    {
        $this->browse(function (Browser $browser) {
            $browser->visit('/tasks/2')
                ->assertInputValue('#title', 'テストタスク')
                ->type('#title', 'test task')
                ->screenshot('task_post_typed')
                ->press('更新')
                ->pause(1000)
                ->assertPathIs('/tasks/2')
                ->screenshot('task_post_pressed');
        });
    }
}

今回は、少しステップが多い。一つずつ見てみよう。

  • URL/tasks/2を表示し
  • id="title"の要素(テキストボックス)内にテストタスクと入力された状態か確認し
  • 同じくid="title"の要素にtest taskと入力し
  • この状態でスクリーンショット(task_post_typed)を撮り
  • 更新ボタンを押し
  • 1秒待ち
  • URLが/tasks/2となっているか確認し
  • 再度スクリーンショット(task_post_pressed)を撮る

という流れだ。テキストボックスなので、確認方法が今までと違っている。 ビューテストを実行してみよう。

$ php artisan dusk
PHPUnit 6.5.8 by Sebastian Bergmann and contributors.

F..F                                                                4 / 4 (100%)

Time: 15.59 seconds, Memory: 14.00MB

There were 2 failures:

1) Tests\Browser\TaskDetailTest::testShowDetail
Did not see expected text [テストタスク] within element [body].
Failed asserting that false is true.

/Users/[ユーザ名]/task-manager/task-manager/vendor/laravel/dusk/src/Concerns/MakesAssertions.php:348
/Users/[ユーザ名]/task-manager/task-manager/vendor/laravel/dusk/src/Concerns/MakesAssertions.php:319
/Users/[ユーザ名]/task-manager/task-manager/tests/Browser/TaskDetailTest.php:20
/Users/[ユーザ名]/task-manager/task-manager/vendor/laravel/dusk/src/Concerns/ProvidesBrowser.php:67
/Users/[ユーザ名]/task-manager/task-manager/tests/Browser/TaskDetailTest.php:22

2) Tests\Browser\TasksIndexTest::testIndexToDetail
Did not see expected text [テストタスク] within element [body].
Failed asserting that false is true.

/Users/[ユーザ名]/task-manager/task-manager/vendor/laravel/dusk/src/Concerns/MakesAssertions.php:348
/Users/[ユーザ名]/task-manager/task-manager/vendor/laravel/dusk/src/Concerns/MakesAssertions.php:319
/Users/[ユーザ名]/task-manager/task-manager/tests/Browser/TasksIndexTest.php:38
/Users/[ユーザ名]/task-manager/task-manager/vendor/laravel/dusk/src/Concerns/ProvidesBrowser.php:67
/Users/[ユーザ名]/task-manager/task-manager/tests/Browser/TasksIndexTest.php:39

FAILURES!
Tests: 4, Assertions: 7, Failures: 2.

おや、失敗してしまった。 しかしよく見ると、今回追加したメソッドでの失敗ではなさそうだ。

・・・よくよく考えると、「詳細画面」を修正したので、 「詳細画面」の表示内容をテストしていた箇所に影響が出たということのようだ。

当然と言えば当然だ。

というわけで、「詳細画面の表示」のビューテストの内容を修正していこう。 つまり、assertSee()としていたものを、今回やったようにassertInputValue()に置き換えるわけだ。

まずは、tests/Browser/TaskDetailTest.php20行目のtestShowDetail()を下記のようにする。






 





()
    public function testShowDetail()
    {
        $this->browse(function (Browser $browser) {
            $browser->visit('/tasks/2')
                ->assertInputValue('#title', 'テストタスク')
                ->screenshot("task_detail");
        });
    }
()

次に、tests/Browser/TasksIndexTest.php38行目のtestIndexToDetail()を下記のように修正する。









 




()
    public function testIndexToDetail() {
        $this->browse(function (Browser $browser) {
            $browser->visit('/tasks')
                ->assertSeeLink('テストタスク')
                ->clickLink('テストタスク')
                ->waitForLocation('/tasks/2', 1)
                ->assertPathIs('/tasks/2')
                ->assertInputValue('#title', 'テストタスク');
        });
    }
}

これで大丈夫、なはずだ。 再びビューテストを実行使用。

$ php artisan dusk
PHPUnit 6.5.8 by Sebastian Bergmann and contributors.

....                                                                4 / 4 (100%)

Time: 12.9 seconds, Memory: 14.00MB

OK (4 tests, 7 assertions)

無事、成功となった。

テストを作っていたおかげで、修正における影響範囲をテスト結果で確認することができた。

今回だと、「詳細画面の表示そのもの」と「一覧画面から詳細画面への遷移確認」だった。 どちらも、「詳細画面」の表示内容が結果として必要なので、画面変更の影響を受けるわけだ。

テストを書きながら開発していくと、 「修正の影響範囲がよくわからない」といった事態や、 「うっかり修正漏れをした」ということを防ぎやすくなることがわかるだろう。

データの操作、画面の作成、と進んだので、次はいよいよコントローラの実装に入ろう。

Last Updated (JST): 7/7/2019, 2:32:08 PM