/**
* This file is part of alf.io.
*
* alf.io is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* alf.io is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with alf.io. If not, see <http://www.gnu.org/licenses/>.
*/
package alfio.manager;
import alfio.manager.i18n.I18nManager;
import alfio.manager.support.TextTemplateGenerator;
import alfio.model.ContentLanguage;
import alfio.model.Event;
import alfio.model.SpecialPrice;
import alfio.model.TicketCategory;
import alfio.model.modification.SendCodeModification;
import alfio.model.user.Organization;
import alfio.repository.SpecialPriceRepository;
import alfio.util.TemplateManager;
import alfio.util.TemplateResource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.context.MessageSource;
import java.time.ZoneId;
import java.util.*;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
@SuppressWarnings("unchecked")
@RunWith(MockitoJUnitRunner.class)
public class SpecialPriceManagerTest {
@Mock
private EventManager eventManager;
@Mock
private Event event;
@Mock
private Organization organization;
@Mock
private TicketCategory ticketCategory;
@Mock
private NotificationManager notificationManager;
@Mock
private SpecialPriceRepository specialPriceRepository;
@Mock
private TemplateManager templateManager;
@Mock
private MessageSource messageSource;
@Mock
private I18nManager i18nManager;
private SpecialPriceManager specialPriceManager;
@Before
public void init() {
List<SpecialPrice> specialPrices = asList(new SpecialPrice(0, "123", 0, 0, "FREE", null, null, null, null), new SpecialPrice(0, "456", 0, 0, "FREE", null, null, null, null));
when(i18nManager.getEventLanguages(anyInt())).thenReturn(Collections.singletonList(ContentLanguage.ITALIAN));
when(messageSource.getMessage(anyString(), any(), any())).thenReturn("text");
when(eventManager.getSingleEvent(anyString(), anyString())).thenReturn(event);
when(eventManager.loadTicketCategories(eq(event))).thenReturn(Collections.singletonList(ticketCategory));
when(ticketCategory.getId()).thenReturn(0);
when(specialPriceRepository.findActiveByCategoryId(eq(0))).thenReturn(specialPrices);
when(eventManager.getEventUrl(eq(event))).thenReturn("http://my-event");
when(eventManager.loadOrganizer(eq(event), anyString())).thenReturn(organization);
when(event.getShortName()).thenReturn("eventName");
when(event.getDisplayName()).thenReturn("Event Name");
when(event.getLocales()).thenReturn(1);
when(event.getZoneId()).thenReturn(ZoneId.systemDefault());
when(specialPriceRepository.markAsSent(any(), anyString(), anyString(), anyString())).thenReturn(1);
setRestricted(ticketCategory, true);
specialPriceManager = new SpecialPriceManager(eventManager, notificationManager, specialPriceRepository, templateManager, messageSource, i18nManager);
}
@Test
public void linkAssigneeToCode() throws Exception {
testAssigneeLink(specialPriceManager, CODES_NOT_REQUESTED);
testAssigneeLink(specialPriceManager, CODES_PARTIALLY_REQUESTED);
testAssigneeLink(specialPriceManager, CODES_REQUESTED);
}
@Test(expected = IllegalArgumentException.class)
public void validationErrorCategoryNotRestricted() throws Exception {
setRestricted(ticketCategory, false);
specialPriceManager.linkAssigneeToCode(Collections.emptyList(), "test", 0, "username");
}
@Test(expected = IllegalArgumentException.class)
public void validationErrorTooManyCodesRequested() throws Exception {
List<SendCodeModification> oneMore = new ArrayList<>();
oneMore.addAll(CODES_REQUESTED);
oneMore.add(new SendCodeModification("123", "", "", ""));
specialPriceManager.linkAssigneeToCode(oneMore, "test", 0, "username");
}
@Test(expected = IllegalArgumentException.class)
public void validationErrorRequestedCodeIsNotAvailable() throws Exception {
List<SendCodeModification> notExistingCode = asList(new SendCodeModification("AAA", "A 123", "123@123", "it"), new SendCodeModification("456", "A 456", "456@456", "en"));
specialPriceManager.linkAssigneeToCode(notExistingCode, "test", 0, "username");
}
@Test(expected = IllegalArgumentException.class)
public void validationErrorCodeRequestedTwice() throws Exception {
List<SendCodeModification> duplicatedCodes = asList(new SendCodeModification("123", "A 123", "123@123", "it"), new SendCodeModification("123", "A 456", "456@456", "en"));
specialPriceManager.linkAssigneeToCode(duplicatedCodes, "test", 0, "username");
}
@Test
public void sendAllCodes() throws Exception {
assertTrue(specialPriceManager.sendCodeToAssignee(CODES_REQUESTED, "", 0, ""));
verify(notificationManager, times(CODES_REQUESTED.size())).sendSimpleEmail(eq(event), anyString(), anyString(), Matchers.any());
}
@Test
public void sendSuccessfulComplete() throws Exception {
assertTrue(specialPriceManager.sendCodeToAssignee(singletonList(new SendCodeModification("123", "me", "me@domain.com", "it")), "", 0, ""));
ArgumentCaptor<TextTemplateGenerator> templateCaptor = ArgumentCaptor.forClass(TextTemplateGenerator.class);
verify(notificationManager).sendSimpleEmail(eq(event), eq("me@domain.com"), anyString(), templateCaptor.capture());
templateCaptor.getValue().generate();
ArgumentCaptor<Map> captor = ArgumentCaptor.forClass(Map.class);
verify(templateManager).renderTemplate(any(Event.class), eq(TemplateResource.SEND_RESERVED_CODE), captor.capture(), eq(Locale.ITALIAN));
Map<String, Object> model = captor.getValue();
assertEquals("123", model.get("code"));
assertEquals(event, model.get("event"));
assertEquals(organization, model.get("organization"));
assertEquals("http://my-event", model.get("eventPage"));
assertEquals("me", model.get("assignee"));
verify(messageSource).getMessage(eq("email-code.subject"), eq(new Object[]{"Event Name"}), eq(Locale.ITALIAN));
}
@Test
public void trimLanguageTag() throws Exception {
assertTrue(specialPriceManager.sendCodeToAssignee(singletonList(new SendCodeModification("123", "me", "me@domain.com", " it")), "", 0, ""));
ArgumentCaptor<TextTemplateGenerator> templateCaptor = ArgumentCaptor.forClass(TextTemplateGenerator.class);
verify(notificationManager).sendSimpleEmail(eq(event), eq("me@domain.com"), anyString(), templateCaptor.capture());
templateCaptor.getValue().generate();
ArgumentCaptor<Map> captor = ArgumentCaptor.forClass(Map.class);
verify(templateManager).renderTemplate(any(Event.class), eq(TemplateResource.SEND_RESERVED_CODE), captor.capture(), eq(Locale.ITALIAN));
Map<String, Object> model = captor.getValue();
assertEquals("123", model.get("code"));
assertEquals(event, model.get("event"));
assertEquals(organization, model.get("organization"));
assertEquals("http://my-event", model.get("eventPage"));
assertEquals("me", model.get("assignee"));
verify(messageSource).getMessage(eq("email-code.subject"), eq(new Object[]{"Event Name"}), eq(Locale.ITALIAN));
}
private static void setRestricted(TicketCategory ticketCategory, boolean restricted) {
when(ticketCategory.isAccessRestricted()).thenReturn(restricted);
}
private static void testAssigneeLink(SpecialPriceManager specialPriceManager, List<SendCodeModification> modifications) {
List<SendCodeModification> sendCodeModifications = specialPriceManager.linkAssigneeToCode(modifications, "test", 0, "username");
assertFalse(sendCodeModifications.isEmpty());
assertEquals(2, sendCodeModifications.size());
sendCodeModifications.forEach(m -> assertEquals("A " + m.getCode(), m.getAssignee()));
}
private static final List<SendCodeModification> CODES_REQUESTED = asList(new SendCodeModification("123", "A 123", "123@123", "it"), new SendCodeModification("456", "A 456", "456@456", "en"));
private static final List<SendCodeModification> CODES_NOT_REQUESTED = asList(new SendCodeModification(null, "A 123", "123@123", "it"), new SendCodeModification(null, "A 456", "456@456", "en"));
private static final List<SendCodeModification> CODES_PARTIALLY_REQUESTED = asList(new SendCodeModification(null, "A 123", "123@123", "it"), new SendCodeModification("456", "A 456", "456@456", "en"));
}