Spring Boot でメール送信する Web アプリケーションを作る ( その19 )( 送信済メール検索画面の作成2 )
概要
Spring Boot でメール送信する Web アプリケーションを作る ( その18 )( 送信済メール検索画面の作成 ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
- 送信済メール検索画面の作成
- 今回はページネーションを実装します。
ソフトウェア一覧
参考にしたサイト
Doma 2 - User Documentation - クエリ - 検索 - 検索オプションを利用した検索
http://doma.readthedocs.org/ja/latest/query/select/#id10
手順
ブランチの作成
- IntelliJ IDEA で 1.0.x-mailsearch-pagenation ブランチを作成します。
ページネーションの実装仕様
以下の仕様で実装します。
- Spring Boot でログイン画面 + 一覧画面 + 登録画面の Webアプリケーションを作る ( その7 )( 検索/一覧画面 ( MyBatis-Spring版 ) 作成2 ) の MyBatis の時と同様に ( org.springframework.data.domain の ) Pageable, Page インターフェースを利用します。
- Controller クラスから Dao クラスを直接呼び出すのではなく、Service クラスを新規作成して Controller → Service → Dao クラスの順で呼び出すように変更します。Service クラスで Pageable インターフェースを実装するオブジェクトを元に SelectOptions クラスのインスタンスを生成する処理と、戻り値の Page インターフェースを実装するオブジェクトの生成処理を実装します。
SQL ファイルの修正
- 値が null でない時だけでなく空でない時にも where 句に条件文を出力しないようにしたいので、SQL ファイルを修正します。src/main/resources/META-INF/ksbysample/webapp/email/web/mailsearch/MailsearchDao の下の selectCondition.sql を リンク先の内容 に変更します。
MailsearchDao インターフェースの修正
src/main/java/ksbysample/webapp/email/web/mailsearch の下の MailsearchDao.java を リンク先の内容 に変更します。
src/test/java/ksbysample/webapp/email/web/mailsearch の下の MailsearchDaoTest.java を リンク先の内容 に変更します。
テストを実行します。testSelectConditionOptions テストメソッドでコンテキストメニューを表示し、「Run 'testSelectConditionO...' with Coverage」を選択し、テストが成功することを確認します。
MailsearchService クラスの作成
- src/main/java/ksbysample/webapp/email/web/mailsearch の下に MailsearchService.java を新規作成します。作成後、リンク先の内容 に変更します。
MailsearchController クラス、Thymeleaf テンプレートファイルの修正
ksbysample-webapp-basic から以下のファイルをコピーします。
src/main/java/ksbysample/webapp/email/web/mailsearch の下の MailsearchController.java を リンク先の内容 に変更します。
src/main/resources/templates/common の下に pagenation.html を新規作成します。作成後、リンク先の内容 に変更します。
src/main/resources/templates/mailsearch の下の mailsearch.html を リンク先の内容 に変更します。
動作確認
Gradle projects View から bootRun タスクを実行して Tomcat を起動します。
ブラウザを起動し http://localhost:8080/mailsearch へアクセスします。今回はページネーションが機能していることを確認します。
1件しかヒットしない場合は以下の画像のようになります。
Run View で Ctrl+F2 を押して Tomcat を停止します。
MailsearchControllerTest クラスの作成
ksbysample-webapp-basic から以下のファイルをコピーします。
src/test/resources/ksbysample/webapp/email/web/mailsearch の下に mailsearchForm_empty.yml, mailsearchForm_toAddr.yml, mailsearchForm_subject.yml, mailsearchForm_name.yml, mailsearchForm_type.yml を新規作成します。作成後、リンク先の内容 に変更します。
src/test/java/ksbysample/webapp/email/web/mailsearch の下に MailsearchControllerTest.java を新規作成します。作成後、リンク先の内容 に変更します。
テストを実行します。MailsearchControllerTest テストメソッドでコンテキストメニューを表示し、「Run 'MailsearchController...' with Coverage」を選択し、テストが成功することを確認します。
commit、Push、Pull Request、マージ
Project View のルートでコンテキストメニューを表示して「Run 'Tests in 'ksbysample...' with Coverage」を選択し、テストが全て成功することを確認します。
Gradle projects View から build タスクを実行し、"BUILD SUCCESSFUL" が出力されることを確認します。
commit します。
GitHub へ Push、1.0.x-mailsearch-pagenation -> 1.0.x へ Pull Request、1.0.x でマージ、1.0.x-mailsearch-pagenation ブランチを削除、をします。
次回は。。。
いくつか気になっている点があるので、その辺を修正します。
- Doma が実行された SQL 文をログに出力しますが、log4jdbc-log4j2 で SQL ファイルを出力するので Doma の方では出力しないようにします。
- Tomcat 起動中に SQL ファイルを修正しても反映されませんでした ( JRebel で起動していてもダメでした )。反映されるようにする方法があるか調査します。
ソースコード
selectCondition.sql
select /*%expand "em" */* from email em where /*%if mailsearchForm.toAddr != null && mailsearchForm.toAddr != "" */ em.to_addr like /* @infix(mailsearchForm.toAddr) */'%t%' /*%end*/ /*%if mailsearchForm.subject != null && mailsearchForm.subject != "" */ and em.subject like /* @infix(mailsearchForm.subject) */'%スト%' /*%end*/ /*%if mailsearchForm.name != null && mailsearchForm.name != "" */ and em.name like /* @infix(mailsearchForm.name) */'%花%' /*%end*/ /*%if mailsearchForm.type != null && mailsearchForm.type.size() > 0 */ and em.type in /* mailsearchForm.type */('1', '3') /*%end*/ order by em.to_addr
- where 句の if 文に
&& mailsearchForm.[Formクラスのフィールド名] != ""
の条件を追加します。type だけは String 型でなく List型のため && mailsearchForm.type.size() > 0
にしています。
MailsearchDao.java
package ksbysample.webapp.email.web.mailsearch; import ksbysample.webapp.email.annotation.dao.ComponentAndAutowiredDomaConfig; import ksbysample.webapp.email.entity.Email; import org.seasar.doma.Dao; import org.seasar.doma.Select; import org.seasar.doma.jdbc.SelectOptions; import java.util.List; @Dao @ComponentAndAutowiredDomaConfig public interface MailsearchDao { @Select List<Email> selectCondition(MailsearchForm mailsearchForm); @Select List<Email> selectCondition(MailsearchForm mailsearchForm, SelectOptions options); }
List<Email> selectCondition(MailsearchForm mailsearchForm, SelectOptions options);
を追加します。
MailsearchDaoTest.java
package ksbysample.webapp.email.web.mailsearch; import ksbysample.webapp.email.Application; import ksbysample.webapp.email.entity.Email; import ksbysample.webapp.email.test.TestDataLoader; import ksbysample.webapp.email.test.TestDataLoaderResource; import ksbysample.webapp.email.test.TestDataResource; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.seasar.doma.Select; import org.seasar.doma.jdbc.SelectOptions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import java.util.Arrays; import java.util.List; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration public class MailsearchDaoTest { @Rule @Autowired public TestDataResource testDataResource; @Rule @Autowired public TestDataLoaderResource testDataLoaderResource; @Autowired private MailsearchDao mailsearchDao; @Test @TestDataLoader("src/test/resources/ksbysample/webapp/email/web/mailsearch/testdata") public void testSelectCondition() throws Exception { MailsearchForm mailsearchForm = new MailsearchForm(); List<Email> emailList = mailsearchDao.selectCondition(mailsearchForm); // emailList.stream().forEach(s -> System.out.println(s.getToAddr())); assertThat(emailList.size(), is(5)); mailsearchForm = new MailsearchForm(); mailsearchForm.setToAddr("t"); mailsearchForm.setSubject("スト"); mailsearchForm.setName("花"); mailsearchForm.setType(Arrays.asList("3")); emailList = mailsearchDao.selectCondition(mailsearchForm); assertThat(emailList.size(), is(1)); mailsearchForm = new MailsearchForm(); mailsearchForm.setName("太郎"); emailList = mailsearchDao.selectCondition(mailsearchForm); assertThat(emailList.size(), is(3)); } @Test @TestDataLoader("src/test/resources/ksbysample/webapp/email/web/mailsearch/testdata") public void testSelectConditionOptions() throws Exception { MailsearchForm mailsearchForm = new MailsearchForm(); List<Email> emailList = mailsearchDao.selectCondition(mailsearchForm); assertThat(emailList.size(), is(5)); assertThat(emailList.get(0).getToAddr(), is("hanako@sample.com")); // offset(0).limit(1) を指定すると最初の1件目だけ取得できる mailsearchForm = new MailsearchForm(); SelectOptions options = SelectOptions.get().offset(0).limit(1).count(); emailList = mailsearchDao.selectCondition(mailsearchForm, options); assertThat(emailList.size(), is(1)); assertThat(emailList.get(0).getToAddr(), is("hanako@sample.com")); // options.getCount() で offset, limit が指定されていない時の全件数を取得できる long count = options.getCount(); assertThat(count, is(5L)); } }
- testSelectConditionOptions テストメソッドを追加します。
MailsearchService.java
package ksbysample.webapp.email.web.mailsearch; import ksbysample.webapp.email.entity.Email; import org.seasar.doma.jdbc.SelectOptions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.List; @Service public class MailsearchService { @Autowired private MailsearchDao mailsearchDao; public Page<Email> searchEmail(MailsearchForm mailsearchForm, Pageable pageable) { int offset = pageable.getPageNumber() * pageable.getPageSize(); int limit = pageable.getPageSize(); SelectOptions options = SelectOptions.get().offset(offset).limit(limit).count(); List<Email> emailList = mailsearchDao.selectCondition(mailsearchForm, options); long count = options.getCount(); Page<Email> page = new PageImpl<Email>(emailList, pageable, count); return page; } }
MailsearchController.java
package ksbysample.webapp.email.web.mailsearch; import ksbysample.webapp.email.entity.Email; import ksbysample.webapp.email.helper.PagenationHelper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/mailsearch") public class MailsearchController { private static final int DEFAULT_PAGEABLE_SIZE = 2; @Autowired private MailsearchService mailsearchService; @RequestMapping public String index(MailsearchForm mailsearchForm , @PageableDefault(size = DEFAULT_PAGEABLE_SIZE, page = 0) Pageable pageable , Model model) { Page<Email> page = mailsearchService.searchEmail(mailsearchForm, pageable); PagenationHelper ph = new PagenationHelper(page); model.addAttribute("page", page); model.addAttribute("ph", ph); return "mailsearch/mailsearch"; } }
private static final int DEFAULT_PAGEABLE_SIZE = 2;
を追加します。ページネーションの動作を確認しやすくするため、1ページの最大表示件数を2件に設定します。private MailsearchDao mailsearchDao;
→private MailsearchService mailsearchService;
へ変更します。- index メソッドを以下のように変更します。
- 引数に
@PageableDefault(size = DEFAULT_PAGEABLE_SIZE, page = 0) Pageable pageable
を追加します。 - データ一覧は
mailsearchService.searchEmail(...)
を呼び出して取得します。 - Thymeleaf テンプレートファイルでページネーションの処理を行うために PagenationHelper クラスのインスタンスを生成します。
- model に page, ph をセットします。
- 引数に
pagenation.html
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <title>xxxxxxxx</title> <!-- Bootstrap core CSS --> <link href="/css/bootstrap.min.css" rel="stylesheet"/> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!--[if lt IE 9]> <script src="/js/html5shiv.min.js"></script> <script src="/js/respond.min.js"></script> <![endif]--> <!-- Custom styles for this template --> <style> <!-- body { padding-top: 50px; } .navbar-brand { font-size: 24px; } .form-group { margin-bottom: 5px; } --> </style> </head> <body> <div th:fragment="pagenation (url, page, ph)"> <div class="row"> <div class="col-xs-12"> <div class="dataTables_paginate paging_bootstrap"> <ul class="pagination"> <li class="prev" th:classappend="${ph.hiddenPrev} ? 'disabled'"> <a class="js-pagenation" th:href="@{${url}(page=${page.number - 1},size=${page.size})}">← Previous</a> </li> <li th:class="${ph.activePage1} ? 'active'"> <a class="js-pagenation" th:href="@{${url}(page=${ph.page1PageValue},size=${page.size})}" th:text="${ph.page1PageValue + 1}">1</a> </li> <li th:class="${ph.activePage2} ? 'active'" th:classappend="${ph.hiddenPage2} ? 'disabled'"> <a class="js-pagenation" th:href="@{${url}(page=${ph.page1PageValue + 1},size=${page.size})}" th:text="${ph.page1PageValue + 2}">2</a> </li> <li th:class="${ph.activePage3} ? 'active'" th:classappend="${ph.hiddenPage3} ? 'disabled'"> <a class="js-pagenation" th:href="@{${url}(page=${ph.page1PageValue + 2},size=${page.size})}" th:text="${ph.page1PageValue + 3}">3</a> </li> <li th:class="${ph.activePage4} ? 'active'" th:classappend="${ph.hiddenPage4} ? 'disabled'"> <a class="js-pagenation" th:href="@{${url}(page=${ph.page1PageValue + 3},size=${page.size})}" th:text="${ph.page1PageValue + 4}">4</a> </li> <li th:class="${ph.activePage5} ? 'active'" th:classappend="${ph.hiddenPage5} ? 'disabled'"> <a class="js-pagenation" th:href="@{${url}(page=${ph.page1PageValue + 4},size=${page.size})}" th:text="${ph.page1PageValue + 5}">5</a> </li> <li class="next" th:classappend="${ph.hiddenNext} ? 'disabled'"> <a class="js-pagenation" th:href="@{${url}(page=${page.number + 1},size=${page.size})}">Next → </a> </li> </ul> </div> </div> </div> </div> </body> </html>
mailsearch.html
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>ksbysample-webapp-email</title> <meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'/> <meta th:replace="common/head-cssjs"/> <style> <!-- .form-group { margin-bottom: 5px; } .table { margin-top: 10px; margin-bottom: 0px; } .table>tbody>tr>td , .table>tbody>tr>th , .table>tfoot>tr>td , .table>tfoot>tr>th , .table>thead>tr>td , .table>thead>tr>th { padding: 5px; } .checkbox label, .radio label { padding-right: 10px; } .pagination > .disabled > a , .pagination > .disabled > a:focus , .pagination > .disabled > a:hover , .pagination > .disabled > span , .pagination > .disabled > span:focus , .pagination > .disabled > span:hover { color: #eee; cursor: not-allowed; background-color: #fff; border-color: #ddd; } --> </style> </head> <body class="skin-blue"> <div class="wrapper"> <!-- Main Header --> <div th:replace="common/mainparts :: main-header"></div> <!-- Left side column. contains the logo and sidebar --> <div th:replace="common/mainparts :: main-sidebar (active='mailsearch')"></div> <!-- Content Wrapper. Contains page content --> <div class="content-wrapper"> <!-- Content Header (Page header) --> <section class="content-header"> <h1> 送信済メール検索画面 </h1> </section> <!-- Main content --> <section class="content"> <div class="row"> <div class="col-xs-12"> <div class="box"> <div class="box-header with-border bg-purple-gradient"> <div class="row"> <div class="col-xs-12"> <form id="mailSearchForm" method="post" action="/mailsearch" th:action="@{/mailsearch}" th:object="${mailsearchForm}" class="form-horizontal"> <div class="form-group"> <label for="toAddr" class="control-label col-sm-2">To</label> <div class="col-sm-10"> <div class="row"><div class="col-sm-8"><div class="input-group"><span class="input-group-addon"><i class="fa fa-envelope"></i></span><input type="text" name="toAddr" id="toAddr" class="form-control input-sm" value="" placeholder="" th:field="*{toAddr}"/></div></div></div> </div> </div> <div class="form-group"> <label for="subject" class="control-label col-sm-2">Subject</label> <div class="col-sm-10"> <div class="row"><div class="col-sm-12"><input type="text" name="subject" id="subject" class="form-control input-sm" value="" placeholder="" th:field="*{subject}"/></div></div> </div> </div> <div class="form-group"> <label for="name" class="control-label col-sm-2">氏名</label> <div class="col-sm-10"> <div class="row"><div class="col-sm-8"><input type="text" name="name" id="name" class="form-control input-sm" value="" placeholder="" th:field="*{name}"/></div></div> </div> </div> <div class="form-group"> <label class="control-label col-sm-2">項目</label> <div class="col-sm-10"> <div class="row"><div class="col-sm-12"> <div class="checkbox"> <label th:each="type : ${T(ksbysample.webapp.email.config.Constant).getInstance().TYPE_MAP.entrySet()}"> <input type="checkbox" name="type" th:value="${type.getKey()}" th:text="${type.getValue()}" th:field="*{type}"/> </label> </div> </div></div> </div> </div> <div class="text-center"> <button type="button" id="search" value="search" class="btn btn-primary bg-gray">検索</button> </div> </form> </div> </div> </div> <div class="box-body"> <div id="maillist_wrapper" class="dataTables_wrapper form-inline" role="grid"> <table id="maillist" class="table table-bordered table-hover dataTable" aria-describedby="maillist_info"> <thead class="bg-purple"> <tr role="row"> <th role="columnheader" tabindex="0" aria-controls="maillist" rowspan="1" colspan="1">To</th> <th role="columnheader" tabindex="0" aria-controls="maillist" rowspan="1" colspan="1">Subject</th> <th role="columnheader" tabindex="0" aria-controls="maillist" rowspan="1" colspan="1">氏名</th> <th role="columnheader" tabindex="0" aria-controls="maillist" rowspan="1" colspan="1">項目</th> </tr> </thead> <tbody role="alert" aria-live="polite" aria-relevant="all"> <tr th:each="email : ${page.content}"> <td th:text="${email.toAddr}">test@sample.com</td> <td th:text="${email.subject}">件名1</td> <td th:text="${email.name}">田中 太郎</td> <td th:text="${T(ksbysample.webapp.email.config.Constant).getInstance().TYPE_MAP.get(email.type)}">資料請求</td> </tr> </tbody> </table> <div id="pagenation" th:include="common/pagenation :: pagenation (url='/mailsearch', page=${page}, ph=${ph})"></div> <form id="pagenationForm" method="post" action="#" th:action="@{#}" th:object="${mailsearchForm}"> <input type="hidden" name="toAddr" id="toAddr" th:value="*{toAddr}"/> <input type="hidden" name="subject" id="subject" th:value="*{subject}"/> <input type="hidden" name="name" id="name" th:value="*{name}"/> <input type="hidden" name="type" id="type" th:each="typeItem : *{type}" th:value="${typeItem}"/> </form> </div> </div> </div> </div> </div> </section> <!-- /.content --> </div> <!-- /.content-wrapper --> </div> <!-- ./wrapper --> <!-- REQUIRED JS SCRIPTS --> <div th:replace="common/bottom-js"></div> <script type="text/javascript"> <!-- $(document).ready(function() { $('#toAddr').focus(); $('#search').bind('click', function(){ $('#mailSearchForm').submit(); }); $('.js-pagenation').each(function(){ $(this).click(function(){ $('#pagenationForm').attr('action', $(this).attr('href')); $(this).attr('href', '#'); $('#pagenationForm').submit(); }); }); }); --> </script> </body> </html>
- ページネーションで押せない部分の文字の色を薄くしたいので、CSS に
.pagination > .disabled > a, , ... { ... }
を追加します。 - ヒットしたデータを表示する部分で tbody タグが複数出力されていることに気づきました。tbody タグに入れていた
th:each="email : ${page.content}"
をその下の tr タグへ移動します。 - ページネーションの HTML の部分を
<div id="pagenation" th:include="common/pagenation :: pagenation (url='/mailsearch', page=${page}, ph=${ph})"></div>
へ変更します。 - ページネーション処理用のフォーム
<form id="pagenationForm" ...> ... </form>
を追加します。 $('.js-pagenation').each(function(){ ... }
を追加します。
mailsearchForm_empty.yml, mailsearchForm_toAddr.yml, mailsearchForm_subject.yml, mailsearchForm_name.yml, mailsearchForm_type.yml
■mailsearchForm_empty.yml
!!ksbysample.webapp.email.web.mailsearch.MailsearchForm toAddr: subject: name:
■mailsearchForm_toAddr.yml
!!ksbysample.webapp.email.web.mailsearch.MailsearchForm toAddr: yyy subject: name:
■mailsearchForm_subject.yml
!!ksbysample.webapp.email.web.mailsearch.MailsearchForm toAddr: subject: スト name:
■mailsearchForm_name.yml
!!ksbysample.webapp.email.web.mailsearch.MailsearchForm toAddr: subject: name: 鈴木
■mailsearchForm_type.yml
!!ksbysample.webapp.email.web.mailsearch.MailsearchForm toAddr: subject: name: type: - 2 - 3
MailsearchControllerTest.java
package ksbysample.webapp.email.web.mailsearch; import ksbysample.webapp.email.Application; import ksbysample.webapp.email.test.*; 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.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.yaml.snakeyaml.Yaml; import static ksbysample.webapp.email.test.CustomModelResultMatchers.modelEx; import static org.hamcrest.Matchers.is; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @RunWith(Enclosed.class) public class MailsearchControllerTest { @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration public static class 初期表示のテスト { @Rule @Autowired public MockMvcResource mvc; @Test public void 送信済メール検索画面を表示する() throws Exception { // 送信済メール検索画面が表示されることを確認する mvc.nonauth.perform(get("/mailsearch")) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("mailsearch/mailsearch")) .andExpect(modelEx().property("page.number", is(0))); } } @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration public static class 検索条件は何も入力しないで検索する場合 { @Rule @Autowired public TestDataResource testDataResource; @Rule @Autowired public TestDataLoaderResource testDataLoaderResource; @Rule @Autowired public MockMvcResource mvc; // テストデータ private MailsearchForm mailsearchFormEmpty = (MailsearchForm) new Yaml().load(getClass().getResourceAsStream("mailsearchForm_empty.yml")); @Test @TestDataLoader("src/test/resources/ksbysample/webapp/email/web/mailsearch/testdata") public void 検索ボタンをクリックすると1ページ目が表示される() throws Exception { mvc.nonauth.perform(TestHelper.postForm("/mailsearch", this.mailsearchFormEmpty)) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("mailsearch/mailsearch")) .andExpect(modelEx().property("page.number", is(0))) .andExpect(modelEx().property("page.size", is(2))) .andExpect(modelEx().property("page.totalPages", is(3))) .andExpect(modelEx().property("ph.page1PageValue", is(0))) .andExpect(modelEx().property("ph.hiddenPrev", is(true))) .andExpect(modelEx().property("ph.hiddenNext", is(false))); } @Test @TestDataLoader("src/test/resources/ksbysample/webapp/email/web/mailsearch/testdata") public void 検索条件はそのままで2ページ目へ() throws Exception { mvc.nonauth.perform(TestHelper.postForm("/mailsearch?page=1&size=2", this.mailsearchFormEmpty)) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("mailsearch/mailsearch")) .andExpect(modelEx().property("page.number", is(1))) .andExpect(modelEx().property("page.size", is(2))) .andExpect(modelEx().property("page.totalPages", is(3))) .andExpect(modelEx().property("ph.page1PageValue", is(0))) .andExpect(modelEx().property("ph.hiddenPrev", is(false))) .andExpect(modelEx().property("ph.hiddenNext", is(false))); } } @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration public static class 検索条件を入力して検索する場合 { @Rule @Autowired public TestDataResource testDataResource; @Rule @Autowired public TestDataLoaderResource testDataLoaderResource; @Rule @Autowired public MockMvcResource mvc; // テストデータ private MailsearchForm mailsearchFormToAddr = (MailsearchForm) new Yaml().load(getClass().getResourceAsStream("mailsearchForm_toAddr.yml")); private MailsearchForm mailsearchFormSubject = (MailsearchForm) new Yaml().load(getClass().getResourceAsStream("mailsearchForm_subject.yml")); private MailsearchForm mailsearchFormName = (MailsearchForm) new Yaml().load(getClass().getResourceAsStream("mailsearchForm_name.yml")); private MailsearchForm mailsearchFormType = (MailsearchForm) new Yaml().load(getClass().getResourceAsStream("mailsearchForm_type.yml")); @Test @TestDataLoader("src/test/resources/ksbysample/webapp/email/web/mailsearch/testdata") public void toAddrのみで検索して3件ヒットする場合() throws Exception { mvc.nonauth.perform(TestHelper.postForm("/mailsearch", this.mailsearchFormToAddr)) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("mailsearch/mailsearch")) .andExpect(modelEx().property("page.number", is(0))) .andExpect(modelEx().property("page.size", is(2))) .andExpect(modelEx().property("page.totalPages", is(2))) .andExpect(modelEx().property("ph.page1PageValue", is(0))) .andExpect(modelEx().property("ph.hiddenPrev", is(true))) .andExpect(modelEx().property("ph.hiddenNext", is(false))); } @Test @TestDataLoader("src/test/resources/ksbysample/webapp/email/web/mailsearch/testdata") public void subjectのみで検索して5件ヒットする場合() throws Exception { mvc.nonauth.perform(TestHelper.postForm("/mailsearch", this.mailsearchFormSubject)) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("mailsearch/mailsearch")) .andExpect(modelEx().property("page.number", is(0))) .andExpect(modelEx().property("page.size", is(2))) .andExpect(modelEx().property("page.totalPages", is(3))) .andExpect(modelEx().property("ph.page1PageValue", is(0))) .andExpect(modelEx().property("ph.hiddenPrev", is(true))) .andExpect(modelEx().property("ph.hiddenNext", is(false))); } @Test @TestDataLoader("src/test/resources/ksbysample/webapp/email/web/mailsearch/testdata") public void nameのみで検索して1件ヒットする場合() throws Exception { mvc.nonauth.perform(TestHelper.postForm("/mailsearch", this.mailsearchFormName)) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("mailsearch/mailsearch")) .andExpect(modelEx().property("page.number", is(0))) .andExpect(modelEx().property("page.size", is(2))) .andExpect(modelEx().property("page.totalPages", is(1))) .andExpect(modelEx().property("ph.page1PageValue", is(0))) .andExpect(modelEx().property("ph.hiddenPrev", is(true))) .andExpect(modelEx().property("ph.hiddenNext", is(true))); } @Test @TestDataLoader("src/test/resources/ksbysample/webapp/email/web/mailsearch/testdata") public void typeのみで検索して2件ヒットする場合() throws Exception { mvc.nonauth.perform(TestHelper.postForm("/mailsearch", this.mailsearchFormType)) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("mailsearch/mailsearch")) .andExpect(modelEx().property("page.number", is(0))) .andExpect(modelEx().property("page.size", is(2))) .andExpect(modelEx().property("page.totalPages", is(1))) .andExpect(modelEx().property("ph.page1PageValue", is(0))) .andExpect(modelEx().property("ph.hiddenPrev", is(true))) .andExpect(modelEx().property("ph.hiddenNext", is(true))); } } }
履歴
2015/06/17
初版発行。