かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その70 )( 完了画面を作成する )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その69 )( 再び eslint-config-airbnb-base をインストールする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Geb のテストを作成するつもりでしたが、完了画面で「入力画面へ」ボタンをクリックして入力画面1へ戻った時にデータがクリアされていないことに気づきましたので、完了画面の処理を実装します。

参照したサイト・書籍

目次

  1. InquiryCompleteController クラスを変更する
  2. 動作確認
  3. InquiryCompleteController クラスのテストを作成する

手順

InquiryCompleteController クラスを変更する

完了画面が表示された時にセッションのデータをクリアするようにします。src/main/java/ksbysample/webapp/bootnpmgeb/web/inquiry/InquiryCompleteController.java の以下の点を変更します。

package ksbysample.webapp.bootnpmgeb.web.inquiry;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpSession;

/**
 * 完了画面用 Controller クラス
 */
@Controller
@RequestMapping("/inquiry/complete")
public class InquiryCompleteController {

    private static final String TEMPLATE_BASE = "web/inquiry";
    private static final String TEMPLATE_COMPLETE = TEMPLATE_BASE + "/complete";

    /**
     * 完了画面 初期表示処理
     *
     * @return 完了画面の Thymeleaf テンプレートファイルのパス
     */
    @GetMapping
    public String index(HttpSession session) {
        session.invalidate();
        return TEMPLATE_COMPLETE;
    }

}
  • index メソッドの以下の点を変更します。
    • 引数に HttpSession session を追加します。
    • session.invalidate(); を追加します。

動作確認

動作確認します。npm run springboot コマンドを実行し Tomcat と smtp4dev を起動した後、ブラウザで http://localhost:9080/inquiry/input/01/ にアクセスします。

入力画面1~3でデータを入力して確認画面を表示します。

f:id:ksby:20180717060048p:plain f:id:ksby:20180717060122p:plain

「送信する」ボタンを押すと完了画面が表示されます。

f:id:ksby:20180717060254p:plain

「入力画面へ」ボタンを押して入力画面1へ戻ります。修正前は入力したデータが表示されていましたが、セッションをクリアするようにしたので表示されなくなりました。

f:id:ksby:20180717060350p:plain

InquiryCompleteController クラスのテストを作成する

src/main/java/ksbysample/webapp/bootnpmgeb/web/inquiry/InquiryCompleteController.java で Ctrl+Shift+T を押して「Create Test」ダイアログを表示してから、以下の画像の値にした後「OK」ボタンをクリックします。「Testing Library」では「Spock」を選択していますが、 Spring Boot + npm + Geb で入力フォームを作ってテストする ( その64 )( 入力画面3を作成する6、@SpringBootTest のテストは Spock+Groovy より JUnit4+Groovy の方が速い? ) で JUnit4+Groovy の方が実行は速いことに気づいたので、テストは JUnit4+Groovy で実装します(「Spock」を選択したのはテストクラスの拡張子を .groovy にしたいためです)。

f:id:ksby:20180717061149p:plain

src/test/groovy/ksbysample/webapp/bootnpmgeb/web/inquiry/InquiryCompleteControllerTest.groovy が新規作成されるので、以下の内容を記述します。

package ksbysample.webapp.bootnpmgeb.web.inquiry

import ksbysample.common.test.helper.TestHelper
import ksbysample.common.test.rule.mail.MailServerResource
import ksbysample.webapp.bootnpmgeb.values.Type1Values
import ksbysample.webapp.bootnpmgeb.values.Type2Values
import ksbysample.webapp.bootnpmgeb.web.inquiry.form.InquiryInput01Form
import ksbysample.webapp.bootnpmgeb.web.inquiry.form.InquiryInput02Form
import ksbysample.webapp.bootnpmgeb.web.inquiry.form.InquiryInput03Form
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.MediaType
import org.springframework.mock.web.MockHttpSession
import org.springframework.test.context.junit4.SpringRunner
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.MvcResult
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import org.springframework.web.context.WebApplicationContext
import org.yaml.snakeyaml.Yaml

import static ksbysample.common.test.matcher.HtmlResultMatchers.html
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrlPattern
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status

@RunWith(SpringRunner)
@SpringBootTest
class InquiryCompleteControllerTest {

    InquiryInput01Form inquiryInput01Form_001 =
            (InquiryInput01Form) new Yaml().load(getClass().getResourceAsStream("InquiryInput01Form_001.yaml"))
    InquiryInput02Form inquiryInput02Form_001 = new InquiryInput02Form(
            zipcode1: "102"
            , zipcode2: "0072"
            , address: "東京都千代田区飯田橋1-1"
            , tel1: "03"
            , tel2: "1234"
            , tel3: "5678"
            , email: "taro.tanaka@sample.co.jp")
    InquiryInput03Form inquiryInput03Form_001 = new InquiryInput03Form(
            type1: Type1Values.PRODUCT.value
            , type2: [Type2Values.ESTIMATE.value, Type2Values.CATALOGUE.value, Type2Values.OTHER.value]
            , inquiry: "これはテストです"
            , survey: ["1", "2", "3", "4", "5", "6", "7", "8"])

    @Rule
    public MailServerResource mailServerResource = new MailServerResource()

    @Autowired
    WebApplicationContext context

    MockMvc mockMvc

    @Before
    void setup() {
        mockMvc = MockMvcBuilders.webAppContextSetup(context)
                .apply(springSecurity())
                .build()
    }

    @Test
    void "完了画面で「入力画面へ」ボタンをクリックして入力画面1へ戻ると入力していたデータがクリアされる"() {
        when: "入力画面1で項目全てに入力して「次へ」ボタンをクリックする"
        MvcResult result = mockMvc.perform(TestHelper.postForm("/inquiry/input/01?move=next", inquiryInput01Form_001).with(csrf()))
                .andExpect(status().isFound())
                .andExpect(redirectedUrlPattern("**/inquiry/input/02"))
                .andReturn()
        MockHttpSession session = result.getRequest().getSession()

        and: "入力画面2で項目全てに入力して「次へ」ボタンをクリックする"
        mockMvc.perform(TestHelper.postForm("/inquiry/input/02?move=next", inquiryInput02Form_001).with(csrf()).session(session))
                .andExpect(status().isFound())
                .andExpect(redirectedUrlPattern("**/inquiry/input/03"))

        and: "入力画面3で項目全てに入力して「次へ」ボタンをクリックする"
        mockMvc.perform(TestHelper.postForm("/inquiry/input/03?move=next", inquiryInput03Form_001).with(csrf()).session(session))
                .andExpect(status().isFound())
                .andExpect(redirectedUrlPattern("**/inquiry/confirm"))

        and: "確認画面で「送信」ボタンをクリックする"
        mockMvc.perform(post("/inquiry/confirm/send").contentType(MediaType.APPLICATION_FORM_URLENCODED).with(csrf()).session(session))
                .andExpect(status().isFound())
                .andExpect(redirectedUrlPattern("**/inquiry/complete/"))

        and: "完了画面を表示する"
        mockMvc.perform(get("/inquiry/complete/").session(session))
                .andExpect(status().isOk())

        expect: "完了画面で「入力画面へ」ボタンをクリックする(入力画面1に単にアクセスする)と入力したデータはクリアされている"
        mockMvc.perform(get("/inquiry/input/01/").session(session))
                .andExpect(status().isOk())
                .andExpect(html("#lastname").val(""))
                .andExpect(html("#firstname").val(""))
                .andExpect(html("#lastkana").val(""))
                .andExpect(html("#firstkana").val(""))
                .andExpect(html("input[name='sex'][checked='checked']").notExists())
                .andExpect(html("#age").val(""))
                .andExpect(html("select[name='job'] option[selected]").notExists())
    }

}

テストを実行して成功することを確認します。

f:id:ksby:20180718002507p:plain

履歴

2018/07/18
初版発行。