package fr.ippon.tatami.bot;
import com.jayway.awaitility.Awaitility;
import fr.ippon.tatami.bot.config.TatamibotConfiguration;
import fr.ippon.tatami.bot.processor.LastUpdateDateTatamibotConfigurationUpdater;
import fr.ippon.tatami.bot.processor.TatamiStatusProcessor;
import fr.ippon.tatami.bot.route.CommonRouteBuilder;
import fr.ippon.tatami.domain.Domain;
import fr.ippon.tatami.domain.User;
import fr.ippon.tatami.repository.DomainRepository;
import fr.ippon.tatami.repository.TatamibotConfigurationRepository;
import fr.ippon.tatami.service.StatusUpdateService;
import fr.ippon.tatami.service.UserService;
import fr.ippon.tatami.test.MockUtils;
import org.apache.camel.Route;
import org.apache.camel.model.FromDefinition;
import org.apache.camel.model.RouteDefinition;
import org.apache.camel.processor.idempotent.MemoryIdempotentRepository;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.hamcrest.CoreMatchers;
import org.hamcrest.collection.IsCollectionWithSize;
import org.joda.time.DateTime;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.List;
import java.util.concurrent.Callable;
import static com.google.common.collect.Sets.newHashSet;
import static com.jayway.awaitility.Awaitility.await;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.mockito.Mockito.*;
public class TatamibotTest extends CamelTestSupport {
private static final Logger log = LoggerFactory.getLogger(TatamibotTest.class);
@Mock
private DomainRepository domainRepository;
@Mock
private TatamibotConfigurationRepository tatamibotConfigurationRepository;
@Mock
private UserService userService;
@Mock
private StatusUpdateService statusUpdateService;
@InjectMocks
private Tatamibot bot;
@InjectMocks
private TatamiStatusProcessor processor; // real one here ...
@InjectMocks
private LastUpdateDateTatamibotConfigurationUpdater lastUpdateDateTatamibotConfigurationUpdater;
private CommonRouteBuilder commonRouteBuilder;
User tatamibotUser = new User();
private MemoryIdempotentRepository idempotentRepository;
@Before
public void setup() throws Exception {
idempotentRepository = new MemoryIdempotentRepository();
processor = new TatamiStatusProcessor();
lastUpdateDateTatamibotConfigurationUpdater = new LastUpdateDateTatamibotConfigurationUpdater();
bot = new Tatamibot();
MockitoAnnotations.initMocks(this); // init bot and processor with mock dependency
ReflectionTestUtils.setField(bot, "idempotentRepository", idempotentRepository);
commonRouteBuilder = new CommonRouteBuilder();
ReflectionTestUtils.setField(commonRouteBuilder, "tatamiStatusProcessor", processor);
ReflectionTestUtils.setField(commonRouteBuilder, "lastUpdateDateTatamibotConfigurationUpdater", lastUpdateDateTatamibotConfigurationUpdater);
// common mock configuration :
Mockito.when(userService.getUserByLogin("tatamibot@ippon.fr")).thenReturn(tatamibotUser);
Mockito.when(tatamibotConfigurationRepository.findTatamibotConfigurationById(Mockito.anyString())).thenReturn(new TatamibotConfiguration());
}
@Test
public void testRssRouteOnly() throws Exception {
TatamibotConfiguration configuration = getRssBotConfiguration();
configuration.setTag("BlogIppon"); // <<< ==== TAG
setupAndLaunchContext(configuration);
Awaitility.await().until(statusUpdateServiceWasCallAtLeast3Times());
String msg1 = "[Ippevent Mobilité – Applications mobiles – ouverture des inscriptions](http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/GcJYERHTfoQ/)";
String msg2 = "[Business – Ippon Technologies acquiert Atomes et renforce son offre Cloud](http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/wK-Y47WGZBQ/)";
String msg3 = "[Les Méthodes Agiles – Définition de l’Agilité](http://feedproxy.google.com/~r/LeBlogDesExpertsJ2ee/~3/hSqyt1MCOoo/)";
Mockito.verify(statusUpdateService).postStatusAsUser(msg1 + " #BlogIppon", tatamibotUser);
Mockito.verify(statusUpdateService).postStatusAsUser(msg2 + " #BlogIppon", tatamibotUser);
Mockito.verify(statusUpdateService).postStatusAsUser(msg3 + " #BlogIppon", tatamibotUser);
Mockito.verifyNoMoreInteractions(statusUpdateService);
// TODO : the repository is updated three times ...
ArgumentCaptor<TatamibotConfiguration> argumentCaptor = ArgumentCaptor.forClass(TatamibotConfiguration.class);
Mockito.verify(tatamibotConfigurationRepository, Mockito.times(3)).updateTatamibotConfiguration(argumentCaptor.capture());
TatamibotConfiguration value = argumentCaptor.getValue();
Assert.assertThat(value.getLastUpdateDate(), CoreMatchers.is(DateTime.parse("2012-12-17T17:35:51Z").toDate()));
Assert.assertTrue(idempotentRepository.contains("ippon.fr-" + msg1));
}
private Callable<Boolean> statusUpdateServiceWasCallAtLeast3Times() {
return MockUtils.mockCalledCallable(statusUpdateService, 3);
}
@Override
public boolean isUseAdviceWith() {
return true; // returning true here to force CamelTestSupport NOT to start camel context
}
private void setupAndLaunchContext(TatamibotConfiguration configuration) throws Exception {
Domain domain = new Domain();
domain.setName("ippon.fr");
Mockito.when(domainRepository.getAllDomains()).thenReturn(newHashSet(domain));
Mockito.when(tatamibotConfigurationRepository.findTatamibotConfigurationsByDomain("ippon.fr")).thenReturn(newHashSet(configuration));
// Note : we have to configure the context ourself as the mocks are used during route creation ..
context.addRoutes(commonRouteBuilder);
context.addRoutes(bot);
// Fix initial delay to speed up tests by 1s
for (RouteDefinition routeDefinition : context.getRouteDefinitions()) {
for (FromDefinition fromDefinition : routeDefinition.getInputs()) {
String uri = fromDefinition.getUri();
if (uri.startsWith("rss:")) {
fromDefinition.setUri(uri + "&consumer.initialDelay=0");
}
}
}
context.start();
List<Route> routes = context.getRoutes();
Assert.assertThat(routes, IsCollectionWithSize.hasSize(2));
// assertThat(routes.get(0).get, hasItems());
}
private TatamibotConfiguration getRssBotConfiguration() {
final String fileUrl = this.getClass().getResource("route/rss.xml").toExternalForm();
TatamibotConfiguration configuration = new TatamibotConfiguration();
configuration.setTatamibotConfigurationId("TEST_CONFIG_ID");
configuration.setType(TatamibotConfiguration.TatamibotType.RSS);
configuration.setDomain("ippon.fr");
// configuration.setUrl("http://feeds.feedburner.com/LeBlogDesExpertsJ2ee?format=xml");
configuration.setUrl(fileUrl);
configuration.setPollingDelay(60); // not used here
configuration.setLastUpdateDate(DateTime.parse("2010-01-01T00:00:00").toDate());
return configuration;
}
}