Railsチュートリアル 第10章 フレンドリーフォワーディングの追加演習 - フレンドリーフォワーディングのリダイレクト先のURLが渡されていないことのテスト（updateアクション編）

# 何についての記事か

「Railsチュートリアル 第10章 演習 - フレンドリーフォワーディング」の発展学習となります。

同演習には、「渡されたURLに初回のみ転送されていることを確認する。具体的には、リダイレクトのURLはデフォルト (プロフィール画面) に戻っていることを確認する。」という内容の出題があります。それであれば、逆に「『ログインしていない状態でRDB上のユーザー情報を更新しようとした』という状況で、フレンドリーフォワーディングのリダイレクト先のURLが渡されていないこと」のテストも必要なはずです。

というわけで、発展学習としてQiita記事を書いてみました。

# 内容

## フレンドリーフォワーディングのリダイレクト先のURLを保存する処理はどこにあるか

[editアクションの場合と同じく](https://qiita.com/rapidliner00/items/2a67497bcb9b2ea93f5a#%E3%83%95%E3%83%AC%E3%83%B3%E3%83%89%E3%83%AA%E3%83%BC%E3%83%95%E3%82%A9%E3%83%AF%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AE%E3%83%AA%E3%83%80%E3%82%A4%E3%83%AC%E3%82%AF%E3%83%88%E5%85%88%E3%81%AEurl%E3%82%92%E4%BF%9D%E5%AD%98%E3%81%99%E3%82%8B%E5%87%A6%E7%90%86%E3%81%AF%E3%81%A9%E3%81%93%E3%81%AB%E3%81%82%E3%82%8B%E3%81%8B)、Usersコントローラーの`logged_in_user`メソッドとなります。

## フレンドリーフォワーディングのリダイレクト先のURLを保存する処理に対応するテスト

上述コードに対応するテストコードは、`test/controllers/users_controller_test.rb`内にあります。`update`アクションに対応するテストは"hould redirect update when not logged in"です。

```ruby:test/controllers/users_controller_test.rb（抜粋）
test "should redirect update when not logged in" do
  patch user_path(@user), params: { user: { name: @user.name,
                                            email: @user.email } }
  assert_not flash.empty?
  assert_redirected_to login_url
end
```

当該テストに記述を追加すれば、「『ログインしていない状態でRDB上のユーザー情報を更新しようとした』という状況で、フレンドリーフォワーディングのリダイレクト先のURLが渡されていないこと」がテストできるはずです。

実際に追加する記述は以下のようになります。

```diff:test/controllers/users_controller_test.rb（抜粋）
  test "should redirect update when not logged in" do
    patch user_path(@user), params: { user: { name: @user.name,
                                              email: @user.email } }
    assert_not flash.empty?
    assert_redirected_to login_url
+   assert_nil session[:forwarding_url]
  end
```

## 前提 - テストコードの特定行に対してテストを実行する

例えば、`test/controllers/users_controller_test.rb`の22行目に対応するテストを実行するには、`rails test`コマンドを以下のように呼び出せばOKです。

```
# rails test test/controllers/users_controller_test.rb:22
```

## `PATCH`リクエストに対して、一時cookiesにリダイレクト先のURLが保存される場合に対するテスト

### 「`PATCH`リクエストに対して、一時cookiesにリダイレクト先のURLが保存される場合」を再現する

`SessionsHelper#store_location`メソッドの記述を変更します。

```diff:app/helpers/sessions_helper.rb
  module SessionsHelper
    ...略

    # アクセスしようとしたURLを覚えておく
    def store_location
-     session[:forwarding_url] = request.original_url if request.get?
+     session[:forwarding_url] = request.original_url if request.patch?
    end
  end
```

`request.get?`を`request.patch?`にことにより、「リクエストの内容が`PATCH`である場合、一時cookiesにリダイレクト先のURLを保存する」という動作にしています。

### 「`PATCH`リクエストに対して、一時cookiesにリダイレクト先のURLが保存される場合」に、`update`アクションに対するテストが失敗することを確認する

```
# rails test test/controllers/users_controller_test.rb:22
Running via Spring preloader in process 1311
Started with run options --seed 7566

 FAIL["test_should_redirect_update_when_not_logged_in", UsersControllerTest, 0.6280409999890253]
 test_should_redirect_update_when_not_logged_in#UsersControllerTest (0.63s)
        Expected "http://www.example.com/users/959740715" to be nil.
        test/controllers/users_controller_test.rb:27:in `block in <class:UsersControllerTest>'

  5/5: [===================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.63188s
1 tests, 3 assertions, 1 failures, 0 errors, 0 skips
```

`test/controllers/users_controller_test.rb`の27行目でテストが失敗しました。当該行には、以下のコードが記述されています。

```ruby:test/controllers/users_controller_test.rb（27行目）
assert_nil session[:forwarding_url]
```

たった今追加したコードですね。想定したテストが正しく行えていることがわかりました。

### `SessionsHelper#store_location`メソッドを元に戻す

テストが正しく実装できていることがわかったので、`SessionsHelper#store_location`メソッドは元に戻しておきましょう。

```diff:app/helpers/sessions_helper.rb
  module SessionsHelper
    ...略

    # アクセスしようとしたURLを覚えておく
    def store_location
-     session[:forwarding_url] = request.original_url if request.patch?
+     session[:forwarding_url] = request.original_url if request.get?
    end
  end
```

## 実装が正しいことの確認

改めて、`test/controllers/users_controller_test.rb`の22行目に対応するテストを実行します。

```
# rails test test/controllers/users_controller_test.rb:22
Running via Spring preloader in process 1324
Started with run options --seed 26169

  5/5: [===================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.56564s
1 tests, 3 assertions, 0 failures, 0 errors, 0 skips
```

テストは無事成功しました。