package in.partake.controller.api.event; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertTrue; import in.partake.app.PartakeApp; import in.partake.app.PartakeTestApp; import in.partake.base.DateTime; import in.partake.base.PartakeException; import in.partake.base.TimeUtil; import in.partake.controller.ActionProxy; import in.partake.controller.api.APIControllerTest; import in.partake.model.IPartakeDAOs; import in.partake.model.access.Transaction; import in.partake.model.dao.DAOException; import in.partake.model.dao.PartakeConnection; import in.partake.model.daofacade.EventDAOFacade; import in.partake.model.dto.Event; import in.partake.model.dto.EventTicket; import in.partake.model.fixture.impl.EventTestDataProvider; import java.util.Collections; import java.util.List; import java.util.UUID; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.node.ObjectNode; import org.junit.Test; public class SearchAPITest extends APIControllerTest { private static final String SEARCH_QUERY = "あ"; @Test public void testSearchEventAllCategory() throws Exception { storeEventBeforeDeadline(); ActionProxy proxy = getActionProxy(POST, "/api/event/search"); addFormParameter(proxy, "query", SEARCH_QUERY); addFormParameter(proxy, "category", "all"); addFormParameter(proxy, "beforeDeadlineOnly", "true"); addFormParameter(proxy, "sortOrder", "score"); addFormParameter(proxy, "maxNum", "10"); proxy.execute(); assertResultOK(proxy); ObjectNode json = getJSON(proxy); assertPublicEventsAreFound(json); assertThat(json.has("reason"), equalTo(false)); } @Test public void testSearchJapaneseQuery() throws Exception { // http://code.google.com/p/partakein/issues/detail?id=233 ActionProxy proxy = getActionProxy(POST, "/api/event/search"); addFormParameter(proxy, "query", EventTestDataProvider.JAPANESE_IDENTIFIER); addFormParameter(proxy, "category", "all"); addFormParameter(proxy, "beforeDeadlineOnly", "true"); addFormParameter(proxy, "sortOrder", "score"); addFormParameter(proxy, "maxNum", "10"); proxy.execute(); assertResultOK(proxy); ObjectNode json = getJSON(proxy); assertPublicEventsAreFound(json); assertThat(json.has("reason"), equalTo(false)); } @Test public void testSearchJapaneseQueryWithBeforeDeadlineOnly() throws Exception { ActionProxy proxy = getActionProxy(POST, "/api/event/search"); addFormParameter(proxy, "query", EventTestDataProvider.JAPANESE_IDENTIFIER); addFormParameter(proxy, "category", "all"); addFormParameter(proxy, "beforeDeadlineOnly", "false"); addFormParameter(proxy, "sortOrder", "score"); addFormParameter(proxy, "maxNum", "10"); proxy.execute(); assertResultOK(proxy); ObjectNode json = getJSON(proxy); assertPublicEventsAreFound(json); assertThat(json.has("reason"), equalTo(false)); } @Test public void testSearchEventWithoutQuery() throws Exception { storeEventBeforeDeadline(); ActionProxy proxy = getActionProxy(POST, "/api/event/search"); // addFormParameter(proxy, "query", null); addFormParameter(proxy, "category", "all"); addFormParameter(proxy, "beforeDeadlineOnly", "true"); addFormParameter(proxy, "sortOrder", "score"); addFormParameter(proxy, "maxNum", "10"); proxy.execute(); assertResultOK(proxy); ObjectNode json = getJSON(proxy); assertThat(json.has("reason"), equalTo(false)); assertPublicEventsAreFound(json); } // ========================================================================= // beforeDeadlineOnly @Test public void testSearchEventBeforeDeadlineOnly() throws Exception { storeEventAfterDeadline(); storeEventBeforeDeadline(); ActionProxy proxy = getActionProxy(POST, "/api/event/search"); addFormParameter(proxy, "query", SEARCH_QUERY); addFormParameter(proxy, "category", "all"); // addFormParameter(proxy, "beforeDeadlineOnly", null); addFormParameter(proxy, "sortOrder", "score"); addFormParameter(proxy, "maxNum", "10"); proxy.execute(); assertResultOK(proxy); ObjectNode json = getJSON(proxy); assertOnlyBeforeDeadlineAreFound(json); } @Test public void testSearchEventIncludeAfterDeadline() throws Exception { storeEventAfterDeadline(); storeEventBeforeDeadline(); ActionProxy proxy = getActionProxy(POST, "/api/event/search"); addFormParameter(proxy, "query", SEARCH_QUERY); addFormParameter(proxy, "category", "all"); addFormParameter(proxy, "beforeDeadlineOnly", "false"); addFormParameter(proxy, "sortOrder", "score"); addFormParameter(proxy, "maxNum", "10"); proxy.execute(); assertResultOK(proxy); ObjectNode json = getJSON(proxy); DateTime now = TimeUtil.getCurrentDateTime(); boolean findEventWhichIsAfterDeadline = false; boolean findEventWhichIsBeforeDeadline = false; for (JsonNode eventJSON : json.get("events")) { Event event = loadEvent(eventJSON.get("id").asText()); List<EventTicket> tickets = loadEventTickets(event.getId()); DateTime deadline = event.acceptsSomeTicketsTill(tickets); if (deadline.isBefore(now)) { findEventWhichIsAfterDeadline = true; } else { findEventWhichIsBeforeDeadline = true; } } assertTrue("見つかるはずのイベントが見つかりませんでした", findEventWhichIsAfterDeadline); assertTrue("見つかるはずのイベントが見つかりませんでした", findEventWhichIsBeforeDeadline); } /** * beforeDeadlineOnlyを省略した場合はtrueであるとみなす */ @Test public void testSearchEventBeforeDeadlineOnlyEmpty() throws Exception { storeEventAfterDeadline(); storeEventBeforeDeadline(); ActionProxy proxy = getActionProxy(POST, "/api/event/search"); addFormParameter(proxy, "query", SEARCH_QUERY); addFormParameter(proxy, "category", "all"); // addFormParameter(proxy, "beforeDeadlineOnly", null); addFormParameter(proxy, "sortOrder", "score"); addFormParameter(proxy, "maxNum", "10"); proxy.execute(); assertResultOK(proxy); ObjectNode json = getJSON(proxy); assertOnlyBeforeDeadlineAreFound(json); } /** * beforeDeadlineOnlyにtrueでもfalseでもない値が渡されたら引数が異常としてエラー */ @Test public void testSearchEventIllegalBeforeDeadlineOnly() throws Exception { storeEventAfterDeadline(); storeEventBeforeDeadline(); ActionProxy proxy = getActionProxy(POST, "/api/event/search"); addFormParameter(proxy, "query", SEARCH_QUERY); addFormParameter(proxy, "category", "all"); addFormParameter(proxy, "beforeDeadlineOnly", "(´・ω・`)"); addFormParameter(proxy, "sortOrder", "score"); addFormParameter(proxy, "maxNum", "10"); proxy.execute(); assertResultOK(proxy); } private Event createEvent() { Event event = PartakeTestApp.getTestService().getTestDataProviderSet().getEventProvider().create(); event.setTitle(SEARCH_QUERY); event.setSummary(SEARCH_QUERY); event.setDescription(SEARCH_QUERY); event.setBeginDate(new DateTime(0L)); event.setCategory("neta"); event.setCreatedAt(new DateTime(0L)); event.setDraft(false); event.setPasscode(null); // privateイベントは検索の対象にならないので公開イベントとして作成 assert event.isSearchable(); return event; } private Event storeEventAfterDeadline() throws DAOException, PartakeException { final Event event = createEvent(); event.setBeginDate(TimeUtil.getCurrentDateTime().nDayBefore(1)); String eventId = new Transaction<String>() { @Override protected String doExecute(PartakeConnection con, IPartakeDAOs daos) throws DAOException, PartakeException { return EventDAOFacade.create(con, daos, event); } }.execute(); UUID ticketId = UUID.randomUUID(); EventTicket ticket = EventTicket.createDefaultTicket(ticketId, eventId); storeEventTicket(ticket); PartakeApp.getEventSearchService().create(event, Collections.singletonList(ticket)); return event; } private Event storeEventBeforeDeadline() throws DAOException, PartakeException { final Event event = createEvent(); event.setBeginDate(TimeUtil.getCurrentDateTime().nDayAfter(1)); String eventId = new Transaction<String>() { @Override protected String doExecute(PartakeConnection con, IPartakeDAOs daos) throws DAOException, PartakeException { return EventDAOFacade.create(con, daos, event); } }.execute(); UUID ticketId = UUID.randomUUID(); EventTicket ticket = EventTicket.createDefaultTicket(ticketId, eventId); storeEventTicket(ticket); PartakeApp.getEventSearchService().create(event, Collections.singletonList(ticket)); return event; } // ========================================================================= // maxNum @Test public void testSearchEventTooLargeMaxNum() throws Exception { ActionProxy proxy = getActionProxy(POST, "/api/event/search"); addFormParameter(proxy, "query", SEARCH_QUERY); addFormParameter(proxy, "category", "all"); addFormParameter(proxy, "beforeDeadlineOnly", "true"); addFormParameter(proxy, "sortOrder", "score"); addFormParameter(proxy, "maxNum", "10000"); proxy.execute(); assertResultOK(proxy); } /** * maxNum省略時はデフォルト(10)と解釈する * @throws Exception */ @Test public void testSearchEventMissingMaxNum() throws Exception { for (int i = 1; i <= 11; ++i) { storeEventBeforeDeadline(); } ActionProxy proxy = getActionProxy(POST, "/api/event/search"); addFormParameter(proxy, "query", SEARCH_QUERY); addFormParameter(proxy, "category", "all"); addFormParameter(proxy, "beforeDeadlineOnly", "true"); addFormParameter(proxy, "sortOrder", "score"); // addFormParameter(proxy, "maxNum", null); proxy.execute(); assertResultOK(proxy); ObjectNode json = getJSON(proxy); assertThat(json.has("reason"), equalTo(false)); assertThat(json.get("events").size(), equalTo(10)); } @Test public void testSearchEventEmptyMaxNum() throws Exception { ActionProxy proxy = getActionProxy(POST, "/api/event/search"); addFormParameter(proxy, "query", SEARCH_QUERY); addFormParameter(proxy, "category", "all"); addFormParameter(proxy, "beforeDeadlineOnly", "true"); addFormParameter(proxy, "sortOrder", "score"); addFormParameter(proxy, "maxNum", ""); proxy.execute(); assertResultOK(proxy); } @Test public void testSearchEventNotNumberMaxNum() throws Exception { ActionProxy proxy = getActionProxy(POST, "/api/event/search"); addFormParameter(proxy, "query", SEARCH_QUERY); addFormParameter(proxy, "category", "all"); addFormParameter(proxy, "beforeDeadlineOnly", "true"); addFormParameter(proxy, "sortOrder", "score"); addFormParameter(proxy, "maxNum", "m(_ _)m"); proxy.execute(); assertResultOK(proxy); } /** * 大文字小文字間違えて指定した場合はデフォルト値が有効になる */ @Test public void testSearchEventNotLowerCamelMaxNum() throws Exception { for (int i = 1; i <= 11; ++i) { storeEventBeforeDeadline(); } ActionProxy proxy = getActionProxy(POST, "/api/event/search"); addFormParameter(proxy, "query", SEARCH_QUERY); addFormParameter(proxy, "category", "all"); addFormParameter(proxy, "beforeDeadlineOnly", "true"); addFormParameter(proxy, "sortOrder", "score"); // addFormParameter(proxy, "maxNum", null); addFormParameter(proxy, "maxnum", "10"); proxy.execute(); assertResultOK(proxy); ObjectNode json = getJSON(proxy); assertThat(json.has("reason"), equalTo(false)); assertThat(json.get("events").size(), equalTo(10)); } @Test public void testOffset() throws Exception { storeEventBeforeDeadline(); storeEventBeforeDeadline(); ActionProxy proxy = getActionProxy(POST, "/api/event/search"); addFormParameter(proxy, "query", SEARCH_QUERY); addFormParameter(proxy, "category", "all"); addFormParameter(proxy, "maxNum", "2"); proxy.execute(); assertResultOK(proxy); ObjectNode json = getJSON(proxy); String expectedId = json.get("events").get(1).get("id").asText(); addFormParameter(proxy, "offset", "1"); proxy.execute(); assertResultOK(proxy); json = getJSON(proxy); String actualId = json.get("events").get(0).get("id").asText(); assertThat(actualId, is(equalTo(expectedId))); } // ========================================================================= // utility private void assertPublicEventsAreFound(ObjectNode json) { assertTrue(json.get("events").isArray()); assertThat(json.get("events").size(), is(greaterThan(0))); } private void assertOnlyBeforeDeadlineAreFound(ObjectNode json) throws PartakeException, DAOException { DateTime now = TimeUtil.getCurrentDateTime(); boolean findEvents = false; for (JsonNode node : json.get("events")) { Event event = loadEvent(node.get("id").asText()); List<EventTicket> tickets = loadEventTickets(event.getId()); DateTime deadline = event.acceptsSomeTicketsTill(tickets); assertThat("締め切り後のイベントが見つかってしまいました", deadline.getTime(), is(greaterThan(now.getTime()))); findEvents = true; } assertTrue("見つかるはずのイベントが見つかりませんでした", findEvents); } }