package org.ryu22e.nico2cal.service; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import static org.mockito.Mockito.*; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import net.fortuna.ical4j.model.Calendar; import net.fortuna.ical4j.model.ComponentList; import net.fortuna.ical4j.model.component.VEvent; import org.joda.time.DateTime; import org.junit.Test; import org.ryu22e.nico2cal.meta.MyCalendarLogMeta; import org.ryu22e.nico2cal.model.MyCalendar; import org.ryu22e.nico2cal.model.MyCalendarLog; import org.ryu22e.nico2cal.model.Nicolive; import org.ryu22e.nico2cal.model.NicoliveIndex; import org.slim3.datastore.Datastore; import org.slim3.tester.AppEngineTestCase; import org.slim3.util.DateUtil; import com.google.api.client.auth.oauth2.AuthorizationCodeFlow; import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.extensions.appengine.auth.oauth2.AppEngineCredentialStore; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.jackson.JacksonFactory; import com.google.api.services.calendar.model.CalendarList; import com.google.api.services.calendar.model.CalendarListEntry; import com.google.appengine.api.NamespaceManager; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.Link; import com.google.appengine.api.datastore.Text; import com.google.appengine.api.mail.MailServicePb.MailMessage; import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserServiceFactory; public final class CalendarServiceTest extends AppEngineTestCase { /** * */ private CalendarService service = new CalendarService(); /** * */ private List<Key> testDataKeys = new LinkedList<Key>(); /** * @return * @throws IOException */ private CalendarService createMockService() throws IOException { CalendarService mockService = spy(new CalendarService()); doReturn( com.google.api.services.calendar.Calendar.builder( new NetHttpTransport(), new JacksonFactory()).build()) .when(mockService) .createGoogleCalendarClientFromUserId("dummy"); CalendarList calendarList = new CalendarList(); calendarList.setItems(Arrays.asList( new CalendarListEntry(), new CalendarListEntry(), new CalendarListEntry())); doReturn(calendarList).when(mockService).getGoogleCalendarList( new User("dummy@gmail.com", "example.com", "dummy")); return mockService; } /* * (non-Javadoc) {@inheritDoc} */ @Override public void setUp() throws Exception { super.setUp(); NamespaceManager.set("test"); // テストデータを登録する。 testDataKeys.clear(); for (int i = 0; i < 99; i++) { Nicolive nicolinve = new Nicolive(); nicolinve.setTitle("テスト" + i); nicolinve.setDescription(new Text("テスト説明文" + i)); DateTime datetime = new DateTime(2011, 1, 1, 0, 0, 0, 0); datetime = datetime.minusDays(i); nicolinve.setOpenTime(datetime.toDate()); nicolinve.setLink(new Link("http://ryu22e.org/" + i)); Key key = Datastore.put(nicolinve); testDataKeys.add(key); NicoliveIndex nicoliveIndex1 = new NicoliveIndex(); nicoliveIndex1.setKeyword("テスト"); nicoliveIndex1.setNicoliveKey(key); NicoliveIndex nicoliveIndex2 = new NicoliveIndex(); nicoliveIndex2.setKeyword("説明"); nicoliveIndex2.setNicoliveKey(key); NicoliveIndex nicoliveIndex3 = new NicoliveIndex(); nicoliveIndex3.setKeyword("文"); nicoliveIndex3.setNicoliveKey(key); testDataKeys.addAll(Datastore.put( nicoliveIndex1, nicoliveIndex2, nicoliveIndex3)); } Nicolive nicolive = new Nicolive(); nicolive.setTitle("テスト"); nicolive.setDescription(new Text("テスト")); DateTime datetime = new DateTime(2011, 1, 1, 0, 0, 0, 0); nicolive.setOpenTime(datetime.toDate()); nicolive.setLink(new Link("http://ryu22e.org/")); testDataKeys.add(Datastore.put(nicolive)); NicoliveIndex nicoliveIndex = new NicoliveIndex(); nicoliveIndex.setKeyword("テスト"); nicoliveIndex.setNicoliveKey(nicolive.getKey()); testDataKeys.add(Datastore.put(nicoliveIndex)); } /* * (non-Javadoc) {@inheritDoc} */ @Override public void tearDown() throws Exception { // テストデータを削除する。 if (0 < testDataKeys.size()) { Datastore.delete(testDataKeys); } super.tearDown(); } /** * @throws Exception */ @Test(expected = IllegalArgumentException.class) public void RSSフィードをiCalendar形式に変換する_パラメータが不正() throws Exception { assertThat(service, is(notNullValue())); CalendarCondition condition = new CalendarCondition(); condition.setStartDate(null); service.getCalendar(condition); } /** * @throws Exception */ @Test(expected = NullPointerException.class) public void RSSフィードをiCalendar形式に変換する_パラメータがnull() throws Exception { assertThat(service, is(notNullValue())); service.getCalendar(null); } /** * @throws Exception */ @Test public void RSSフィードをiCalendar形式に変換する_該当するデータが存在する() throws Exception { assertThat(service, is(notNullValue())); CalendarCondition condition = new CalendarCondition(); DateTime startDate = new DateTime(2011, 1, 1, 0, 0, 0, 0); startDate = startDate.minusDays(7); condition.setStartDate(startDate.toDate()); condition.setKeywords(Arrays.asList("テスト", "説明")); Calendar calendar = service.getCalendar(condition); assertThat(calendar, not(nullValue())); assertThat(calendar.getProperty("PRODID").getValue(), is("nico2ical")); assertThat(calendar.getProperty("VERSION").getValue(), is("2.0")); assertThat( calendar.getProperty("X-WR-CALNAME").getValue(), is("ニコニコ生放送")); ComponentList components = calendar.getComponents(); assertThat(components, is(notNullValue())); assertThat(components.size(), is(8)); // DTSTARTが古い順にイベントが並んでいる。 int i = 7; for (Object object : components) { assertThat(object, is(notNullValue())); assertThat(object, is(instanceOf(VEvent.class))); VEvent event = (VEvent) object; assertThat(event.getSummary().getValue(), is("テスト" + i)); assertThat(event.getDescription().getValue(), is("テスト説明文" + i)); assertThat(event.getUrl().getValue(), is("http://ryu22e.org/" + i)); DateTime datetime = new DateTime(2011, 1, 1, 0, 0, 0, 0); datetime = datetime.minusDays(i); assertThat(event.getStartDate().getDate(), is(notNullValue())); assertThat( DateUtil.toString(event.getStartDate().getDate()), is(DateUtil.toString(datetime.toDate()))); assertThat(event.getEndDate(), is(notNullValue())); assertThat( DateUtil.toString(event.getEndDate().getDate()), is(DateUtil.toString(datetime.toDate()))); i--; } } /** * @throws Exception */ @Test public void RSSフィードをiCalendar形式に変換する_該当するデータが存在しない() throws Exception { assertThat(service, is(notNullValue())); CalendarCondition condition = new CalendarCondition(); DateTime startDate = new DateTime(2011, 1, 2, 0, 0, 0, 0); condition.setStartDate(startDate.toDate()); Calendar calendar = service.getCalendar(condition); // データが存在しない場合でもnullにはならない。 assertThat(calendar, not(nullValue())); // イベントなしのiCalendar形式データが取得される。 assertThat(calendar.getProperty("PRODID").getValue(), is("nico2ical")); assertThat(calendar.getProperty("VERSION").getValue(), is("2.0")); assertThat( calendar.getProperty("X-WR-CALNAME").getValue(), is("ニコニコ生放送")); ComponentList components = calendar.getComponents(); assertThat(components, is(notNullValue())); assertThat(components.size(), is(0)); } /** * @throws Exception */ @Test public void GoogleCalendarAPI用Flowを取得する() throws Exception { assertThat(service, is(notNullValue())); AuthorizationCodeFlow flow = service.createNewGoogleCalendarApiFlow(); assertThat(flow, is(notNullValue())); } /** * @throws Exception */ @Test(expected = NullPointerException.class) public void GoogleCalendarAPI用Clientを取得する_パラメータがnull() throws Exception { CalendarService mockService = createMockService(); assertThat(mockService, is(notNullValue())); mockService.createGoogleCalendarClient(null); } /** * @throws Exception */ @Test public void GoogleCalendarAPI用Clientを取得する() throws Exception { CalendarService mockService = createMockService(); assertThat(mockService, is(notNullValue())); tester.environment.setEmail("dummy@gmail.com"); Map<String, Object> envAttributes = new HashMap<String, Object>(); envAttributes.put( "com.google.appengine.api.users.UserService.user_id_key", "42"); tester.environment.setAttributes(envAttributes); com.google.api.services.calendar.Calendar calendar = mockService.createGoogleCalendarClient(new User( "dummy@gmail.com", "example.com", "dummy")); assertThat(calendar, is(notNullValue())); verify(mockService, times(1)).createGoogleCalendarClientFromUserId( "dummy"); } /** * @throws Exception */ @Test public void GoogleCalendarのカレンダー一覧を取得する_ログインしている() throws Exception { CalendarService mockService = createMockService(); assertThat(mockService, is(notNullValue())); User user = new User("dummy@gmail.com", "example.com", "dummy"); CalendarList feed = mockService.getGoogleCalendarList(user); assertThat(feed, is(notNullValue())); assertThat(feed.getItems(), is(notNullValue())); assertThat(feed.getItems().size(), is(3)); verify(mockService, times(1)).getGoogleCalendarList(user); } /** * @throws Exception */ @Test(expected = AssertionError.class) public void 連携対象のGoogleCalendarを登録する_ログインしていない() throws Exception { assertThat(service, is(notNullValue())); MyCalendar myCalendar = new MyCalendar(); myCalendar.setCalendarId("test1"); service.putMyCalendar(myCalendar); } /** * @throws Exception */ @Test public void 連携対象のGoogleCalendarを登録する_ログインしている() throws Exception { assertThat(service, is(notNullValue())); tester.environment.setEmail("dummy@gmail.com"); MyCalendar myCalendar = new MyCalendar(); myCalendar.setCalendarId("test1"); myCalendar.setKeyword("keyword1 keyword2"); Key key = service.putMyCalendar(myCalendar); MyCalendar storedMyCalendar = Datastore.getOrNull(MyCalendar.class, key); assertThat(storedMyCalendar, is(notNullValue())); assertThat(storedMyCalendar.getUser(), is(notNullValue())); assertThat(storedMyCalendar.getUser().getEmail(), is("dummy@gmail.com")); } /** * @throws Exception */ @Test public void 連携対象のGoogleCalendarを登録する_既に登録されたデータを上書きする() throws Exception { assertThat(service, is(notNullValue())); tester.environment.setEmail("dummy@gmail.com"); // テストデータの登録。 MyCalendar testData = new MyCalendar(); testData.setCalendarId("test1"); testData.setUser(UserServiceFactory.getUserService().getCurrentUser()); Key testDataKey = Datastore.put(testData); MyCalendar myCalendar = new MyCalendar(); myCalendar.setCalendarId("test2"); myCalendar.setKeyword("keyword1 keyword2 keyword3 keyword4"); Key key = service.putMyCalendar(myCalendar); MyCalendar storedMyCalendar = Datastore.getOrNull(MyCalendar.class, key); assertThat(storedMyCalendar, is(notNullValue())); assertThat(storedMyCalendar.getKey(), is(testDataKey)); assertThat(storedMyCalendar.getCalendarId(), is("test2")); assertThat( storedMyCalendar.getKeyword(), is("keyword1 keyword2 keyword3 keyword4")); } /** * @throws Exception */ @Test(expected = NullPointerException.class) public void 連携対象のGoogleCalendarを登録する_パラメータmyCalendarがnull() throws Exception { assertThat(service, is(notNullValue())); tester.environment.setEmail("dummy@gmail.com"); service.putMyCalendar(null); } /** * @throws Exception */ @Test(expected = NullPointerException.class) public void 連携対象のGoogleCalendarを登録する_パラメータcalendarIdがnull() throws Exception { assertThat(service, is(notNullValue())); tester.environment.setEmail("dummy@gmail.com"); MyCalendar myCalendar = new MyCalendar(); myCalendar.setCalendarId(null); service.putMyCalendar(myCalendar); } /** * @throws Exception */ @Test public void データストア上の連携対象のGoogleCalendarを取得する_ログインしていない場合() throws Exception { assertThat(service, is(notNullValue())); MyCalendar myCalendar = new MyCalendar(); myCalendar.setCalendarId("test1"); myCalendar .setUser(UserServiceFactory.getUserService().getCurrentUser()); Datastore.put(myCalendar); MyCalendar result = service.getCurrentMyCalendar(); assertThat(result, is(nullValue())); } /** * @throws Exception */ @Test public void データストア上の連携対象のGoogleCalendarを取得する_データが存在する場合() throws Exception { assertThat(service, is(notNullValue())); tester.environment.setEmail("dummy@gmail.com"); MyCalendar myCalendar = new MyCalendar(); myCalendar.setCalendarId("test1"); myCalendar .setUser(UserServiceFactory.getUserService().getCurrentUser()); Key key = Datastore.put(myCalendar); MyCalendar result = service.getCurrentMyCalendar(); assertThat(result, is(notNullValue())); assertThat(result.getKey(), is(key)); } /** * @throws Exception */ @Test public void データストア上の連携対象のGoogleCalendarを取得する_データが存在しない場合() throws Exception { assertThat(service, is(notNullValue())); tester.environment.setEmail("dummy@gmail.com"); MyCalendar result = service.getCurrentMyCalendar(); assertThat(result, is(nullValue())); } /** * @throws Exception */ @Test public void GoogleCalendar連携をやめる_ログインしている場合() throws Exception { assertThat(service, is(notNullValue())); tester.environment.setEmail("dummy@gmail.com"); Map<String, Object> envAttributes = new HashMap<String, Object>(); envAttributes.put( "com.google.appengine.api.users.UserService.user_id_key", "42"); tester.environment.setAttributes(envAttributes); // テストデータの登録。 MyCalendar testData = new MyCalendar(); testData.setCalendarId("test1"); testData.setUser(UserServiceFactory.getUserService().getCurrentUser()); Key testDataKey = Datastore.put(testData); Credential credential = new GoogleCredential(); new AppEngineCredentialStore().store("42", credential); assertThat( new AppEngineCredentialStore().load("42", credential), is(true)); service.disConnectMyCalendar(); MyCalendar result = Datastore.getOrNull(MyCalendar.class, testDataKey); assertThat(result, is(notNullValue())); assertThat(result.isDisabled(), is(true)); assertThat( new AppEngineCredentialStore().load("42", credential), is(false)); } /** * @throws Exception */ @Test public void GoogleCalendar連携をやめる_元々連携していない場合() throws Exception { assertThat(service, is(notNullValue())); tester.environment.setEmail("dummy@gmail.com"); Map<String, Object> envAttributes = new HashMap<String, Object>(); envAttributes.put( "com.google.appengine.api.users.UserService.user_id_key", "42"); tester.environment.setAttributes(envAttributes); // 例外は発生しない。 service.disConnectMyCalendar(); } /** * @throws Exception */ @Test public void GoogleCalendar連携をやめる_ログインしていない場合() throws Exception { assertThat(service, is(notNullValue())); // テストデータの登録。 MyCalendar testData = new MyCalendar(); testData.setCalendarId("test1"); testData.setUser(UserServiceFactory.getUserService().getCurrentUser()); Key testDataKey = Datastore.put(testData); Credential credential = new GoogleCredential(); new AppEngineCredentialStore().store("42", credential); assertThat( new AppEngineCredentialStore().load("42", credential), is(true)); service.disConnectMyCalendar(); int count = Datastore.query(MyCalendar.class, testDataKey).count(); assertThat(count, is(1)); assertThat( new AppEngineCredentialStore().load("42", credential), is(true)); } /** * @throws Exception */ @Test public void 連携対象カレンダーのリストを取得する() throws Exception { assertThat(service, is(notNullValue())); // テストデータの登録。 List<MyCalendar> testDataList = new ArrayList<MyCalendar>(); for (int i = 0; i < 10; i++) { MyCalendar myCalendar = new MyCalendar(); myCalendar.setCalendarId("test" + 1); myCalendar.setUser(new User( "test" + 1 + "@gmail.com", "example.com", "test" + 1)); myCalendar.setDisabled(false); testDataList.add(myCalendar); } List<Key> testDatakeys = Datastore.put(testDataList); MyCalendar disabledMyCalendar = new MyCalendar(); disabledMyCalendar.setCalendarId("disabledCalendarId"); disabledMyCalendar.setUser(new User( "test" + 1 + "@gmail.com", "example.com", "test" + 1)); disabledMyCalendar.setDisabled(true); Datastore.put(disabledMyCalendar); List<MyCalendar> result = service.getMyCalendars(); assertThat(result, is(notNullValue())); List<Key> resultKeys = new ArrayList<Key>(); for (MyCalendar myCalendar : result) { resultKeys.add(myCalendar.getKey()); } assertThat(resultKeys, is(testDatakeys)); } /** * @throws Exception */ @Test public void 連携対象カレンダーのリストを取得する_データが存在しない場合() throws Exception { assertThat(service, is(notNullValue())); List<MyCalendar> result = service.getMyCalendars(); assertThat(result, is(notNullValue())); assertThat(result.size(), is(0)); } /** * @throws Exception */ @Test public void 連携対象カレンダーのキーリストを取得する() throws Exception { assertThat(service, is(notNullValue())); // テストデータの登録。 List<MyCalendar> testDataList = new ArrayList<MyCalendar>(); for (int i = 0; i < 10; i++) { MyCalendar myCalendar = new MyCalendar(); myCalendar.setCalendarId("test" + 1); myCalendar.setUser(new User( "test" + 1 + "@gmail.com", "example.com", "test" + 1)); myCalendar.setDisabled(false); testDataList.add(myCalendar); } List<Key> testDatakeys = Datastore.put(testDataList); MyCalendar disabledMyCalendar = new MyCalendar(); disabledMyCalendar.setCalendarId("disabledCalendarId"); disabledMyCalendar.setUser(new User( "test" + 1 + "@gmail.com", "example.com", "test" + 1)); disabledMyCalendar.setDisabled(true); Datastore.put(disabledMyCalendar); List<Key> result = service.getMyCalendarKeys(); assertThat(result, is(notNullValue())); assertThat(result, is(testDatakeys)); } /** * @throws Exception */ @Test public void 連携対象カレンダーのキーリストを取得する_データが存在しない() throws Exception { assertThat(service, is(notNullValue())); List<Key> result = service.getMyCalendarKeys(); assertThat(result, is(notNullValue())); assertThat(result.size(), is(0)); } /** * @throws Exception */ @Test public void GoogleCalendarにニコニコ生放送の放送予定日をインポートする() throws Exception { CalendarService mockService = createMockService(); assertThat(mockService, is(notNullValue())); User user = new User("dummy@gmail.com", "example.com", "dummy"); doReturn( com.google.api.services.calendar.Calendar.builder( new NetHttpTransport(), new JacksonFactory()).build()) .when(mockService) .createGoogleCalendarClient(user); // テストデータの登録。 List<Nicolive> testDataList = new ArrayList<Nicolive>(); for (int i = 0; i < 10; i++) { Nicolive nicolive = new Nicolive(); nicolive.setTitle("ほげほげ"); nicolive.setDescription(new Text("ほげほげ説明文")); DateTime datetime = new DateTime(); nicolive.setOpenTime(datetime.toDate()); nicolive.setLink(new Link("http://ryu22e.org/")); testDataList.add(nicolive); } List<Key> testDataKeys = Datastore.put(testDataList); MyCalendar myCalendar = new MyCalendar(); myCalendar.setCalendarId("calendar1"); myCalendar.setUser(user); Key myCalendarKey = Datastore.put(myCalendar); mockService.importToMyCalendar(myCalendarKey); MyCalendarLogMeta ml = MyCalendarLogMeta.get(); MyCalendarLog myCalendarLog = Datastore .query(ml) .filter( ml.user.equal(user), ml.calendarId.equal("calendar1")) .asSingle(); assertThat(myCalendarLog, is(notNullValue())); assertThat(myCalendarLog.getNicoliveKeys(), is(testDataKeys)); } /** * @throws Exception */ @Test public void GoogleCalendarインポートに失敗した旨をユーザーにメールで通知する() throws Exception { assertThat(service, is(notNullValue())); MyCalendar myCalendar = new MyCalendar(); myCalendar.setCalendarId("calendar1"); myCalendar.setUser(new User("dummy@gmail.com", "example.com", "dummy")); service.sendImportErrorMail(myCalendar); assertThat(tester.mailMessages.size(), is(1)); MailMessage mailMessage = tester.mailMessages.get(0); assertThat(mailMessage.tos().size(), is(1)); assertThat(mailMessage.tos().get(0), is("dummy@gmail.com")); assertThat(mailMessage.getSender(), is("ryu22e@gmail.com")); assertThat( mailMessage.getSubject(), is("Google Calendarへのインポートに失敗しました")); assertThat(mailMessage.getTextBody(), is(notNullValue())); assertThat(mailMessage.getTextBody(), not("")); } }