/* * Copyright (c) 2010 Lockheed Martin Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.eurekastreams.server.action.execution.notification; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import org.apache.commons.lang.text.StrLookup; import org.eurekastreams.server.action.execution.notification.TemplateEmailBuilder.HtmlEncodingLookup; import org.eurekastreams.server.domain.EntityType; import org.eurekastreams.server.domain.NotificationDTO; import org.eurekastreams.server.domain.NotificationType; import org.eurekastreams.server.domain.SystemSettings; import org.eurekastreams.server.domain.stream.BaseObjectType; import org.eurekastreams.server.persistence.mappers.DomainMapper; import org.eurekastreams.server.persistence.mappers.requests.MapperRequest; import org.eurekastreams.server.search.modelview.PersonModelView; import org.eurekastreams.server.service.actions.strategies.EmailerFactory; import org.hamcrest.Matchers; import org.jmock.Expectations; import org.jmock.Mockery; import org.jmock.integration.junit4.JUnit4Mockery; import org.jmock.lib.legacy.ClassImposteriser; import org.junit.Before; import org.junit.Test; /** * Tests the general email builder. */ @SuppressWarnings("unchecked") public class TemplateEmailBuilderTest { /** Test data. */ private static final long RECIPIENT1_ID = 1111L; /** Test data. */ private static final long RECIPIENT2_ID = 1112L; /** Test data. */ private static final String RECIPIENT1_EMAIL = "spammed1@example.com"; /** Test data. */ private static final String RECIPIENT2_EMAIL = "spammed2@example.com"; /** Test data. */ private static final long ACTOR_ID = 2222L; /** Test data. */ private static final String ACTOR_NAME = "Somebody Active"; /** Test data. */ private static final long ACTIVITY_ID = 4444L; /** Test data. */ private static final long DESTINATION_ID = 5555L; /** Test data. */ private static final String GROUP_NAME = "Some Group"; /** Test data. */ private static final NotificationType NOTIFICATION_TYPE = NotificationType.COMMENT_TO_COMMENTED_POST; /** Context for building mock objects. */ private final Mockery context = new JUnit4Mockery() { { setImposteriser(ClassImposteriser.INSTANCE); } }; /** SUT. */ private TemplateEmailBuilder sut; /** Fixture: For sending email. */ private EmailerFactory emailer = context.mock(EmailerFactory.class); /** Fixture: For getting person info. */ private DomainMapper<List<Long>, List<PersonModelView>> peopleMapper = context.mock(DomainMapper.class, "PeopleMapper"); /** Fixture: For getting system settings. */ private DomainMapper<MapperRequest<SystemSettings>, SystemSettings> systemSettingsMapper = context.mock( DomainMapper.class, "SystemSettings"); /** Fixture: message. */ private MimeMessage message = context.mock(MimeMessage.class); /** Fixture: person recipient of email. */ private PersonModelView recipientPerson1 = new PersonModelView() { { setEmail(RECIPIENT1_EMAIL); } }; /** Fixture: person recipient of email. */ private PersonModelView recipientPerson2 = new PersonModelView() { { setEmail(RECIPIENT2_EMAIL); } }; /** Fixture: system settings. */ private SystemSettings systemSettings = new SystemSettings(); /** Fixture: notification. */ private NotificationDTO notification; /** * Constructor; one-time setup. */ public TemplateEmailBuilderTest() { systemSettings.setSiteLabel("SiteLabel"); systemSettings.setSupportEmailAddress("SupportEmailAddress"); systemSettings.setSupportPhoneNumber("SupportPhoneNumber"); systemSettings.setSupportStreamGroupDisplayName("SupportStreamGroupDisplayName"); systemSettings.setSupportStreamGroupShortName("SupportStreamGroupShortName"); } /** * Common setup before each test. * * @throws Exception * Possibly. */ @Before public void setUp() throws Exception { notification = new NotificationDTO(Collections.singletonList(RECIPIENT1_ID), NOTIFICATION_TYPE, 0L); context.checking(new Expectations() { { allowing(systemSettingsMapper).execute(with(any(MapperRequest.class))); will(returnValue(systemSettings)); } }); } /** * Expectations to ignore recipients (for tests focused on other aspects). * * @throws MessagingException * Shouldn't. */ private void setupIgnoreRecipientsExpectations() throws MessagingException { final List<PersonModelView> peopleList = new ArrayList<PersonModelView>(); context.checking(new Expectations() { { allowing(peopleMapper); will(returnValue(peopleList)); ignoring(emailer).setTo(with(any(MimeMessage.class)), with(any(String.class))); ignoring(emailer).setCc(with(any(MimeMessage.class)), with(any(String.class))); ignoring(emailer).setBcc(with(any(MimeMessage.class)), with(any(String.class))); } }); } /** * Core functionality shared by the data use tests. * * @param template * The base template to use. * @param expectedText * The expected resulting text. * @throws Exception * Shouldn't. */ private void coreDataUseTest(final String template, final String expectedText) throws Exception { setupIgnoreRecipientsExpectations(); context.checking(new Expectations() { { oneOf(emailer).setSubject(with(same(message)), with(equal("S:" + expectedText))); oneOf(emailer).setTextBody(with(same(message)), with(equal("T:" + expectedText))); oneOf(emailer).setHtmlBody(with(same(message)), with(equal("H:" + expectedText))); } }); sut = new TemplateEmailBuilder(emailer, peopleMapper, systemSettingsMapper, null, "S:" + template, "T:" + template, "H:" + template); sut.build(notification, message); context.assertIsSatisfied(); } /** * Tests using actor data. * * @throws Exception * Shouldn't. */ @Test public void testBuildUsingActor() throws Exception { notification.setActorId(ACTOR_ID); notification.setActorAccountId("ActorAccount"); notification.setActorName(ACTOR_NAME); coreDataUseTest("$(actor.id)/$(actor.accountid)/$(actor.name)", ACTOR_ID + "/ActorAccount/" + ACTOR_NAME); } /** * Tests using activity data. * * @throws Exception * Shouldn't. */ @Test public void testBuildUsingActivity() throws Exception { notification.setActivity(ACTIVITY_ID, BaseObjectType.BOOKMARK); coreDataUseTest("$(activity.id)/$(activity.type)", ACTIVITY_ID + "/link"); } /** * Tests using activity data. * * @throws Exception * Shouldn't. */ @Test public void testBuildUsingActivity2() throws Exception { notification.setActivity(ACTIVITY_ID, BaseObjectType.VIDEO); coreDataUseTest("$(activity.id)/$(activity.type)", ACTIVITY_ID + "/video"); } /** * Tests using destination data. * * @throws Exception * Shouldn't. */ @Test public void testBuildUsingDestination() throws Exception { notification.setDestination(DESTINATION_ID, EntityType.ORGANIZATION, "myorg", "My Organization"); coreDataUseTest("$(dest.id)/$(dest.type)/$(dest.uniqueid)/$(dest.name)/$(dest.page)", DESTINATION_ID + "/ORGANIZATION/myorg/My Organization/organizations"); } /** * Tests using destination data. * * @throws Exception * Shouldn't. */ @Test public void testBuildUsingAuxiliary() throws Exception { notification.setAuxiliary(EntityType.GROUP, "mygroup", GROUP_NAME); coreDataUseTest("$(aux.type)/$(aux.uniqueid)/$(aux.name)/$(aux.page)", "GROUP/mygroup/" + GROUP_NAME + "/groups"); } /** * Tests using extra properties. * * @throws Exception * Shouldn't. */ @Test public void testBuildWithExtraProperties() throws Exception { notification.setActorId(ACTOR_ID); notification.setActorName(ACTOR_NAME); final String template = "$(actor.id)/$(actor.name)/$(key1)"; final String expectedText = ACTOR_ID + "/" + ACTOR_NAME + "/value1"; setupIgnoreRecipientsExpectations(); context.checking(new Expectations() { { oneOf(emailer).setSubject(with(same(message)), with(equal(expectedText))); oneOf(emailer).setTextBody(with(same(message)), with(equal(expectedText))); oneOf(emailer).setHtmlBody(with(same(message)), with(equal(expectedText))); } }); Map<String, String> extraProperties = new HashMap<String, String>(); extraProperties.put("key1", "value1"); extraProperties.put("actor.id", "**" + Long.toString(ACTOR_ID + 4) + "**"); sut = new TemplateEmailBuilder(emailer, peopleMapper, systemSettingsMapper, extraProperties, template, template, template); sut.build(notification, message); context.assertIsSatisfied(); } /** * Tests using invocation properties. * * @throws Exception * Shouldn't. */ @Test public void testBuildWithInvocationProperties() throws Exception { notification.setActorId(ACTOR_ID); notification.setActorName(ACTOR_NAME); final String template = "$(actor.id)/$(actor.name)/$(key1)/$(key2)/$(key3)"; final String expectedText = ACTOR_ID + "/" + ACTOR_NAME + "/value1/value2/valueC"; setupIgnoreRecipientsExpectations(); context.checking(new Expectations() { { oneOf(emailer).setSubject(with(same(message)), with(equal(expectedText))); oneOf(emailer).setTextBody(with(same(message)), with(equal(expectedText))); oneOf(emailer).setHtmlBody(with(same(message)), with(equal(expectedText))); } }); Map<String, String> extraProperties = new HashMap<String, String>(); extraProperties.put("key1", "value1"); extraProperties.put("key2", "value2"); extraProperties.put("actor.id", "**" + Long.toString(ACTOR_ID + 4) + "**"); Map<String, String> invocationProperties = new HashMap<String, String>(); invocationProperties.put("key2", "valueB"); invocationProperties.put("key3", "valueC"); sut = new TemplateEmailBuilder(emailer, peopleMapper, systemSettingsMapper, extraProperties, template, template, template); sut.build(notification, invocationProperties, message); context.assertIsSatisfied(); } /** * Tests with one recipient. * * @throws Exception * Shouldn't. */ @Test public void testBuildWithOneRecipient() throws Exception { notification.setRecipientIds(Collections.singletonList(RECIPIENT1_ID)); context.checking(new Expectations() { { oneOf(peopleMapper).execute(with(equal(Collections.singletonList(RECIPIENT1_ID)))); will(returnValue(Collections.singletonList(recipientPerson1))); oneOf(emailer).setTo(with(same(message)), with(equal(RECIPIENT1_EMAIL))); ignoring(emailer).setTextBody(with(any(MimeMessage.class)), with(any(String.class))); ignoring(emailer).setHtmlBody(with(any(MimeMessage.class)), with(any(String.class))); ignoring(emailer).setSubject(with(any(MimeMessage.class)), with(any(String.class))); } }); sut = new TemplateEmailBuilder(emailer, peopleMapper, systemSettingsMapper, null, "", "", ""); sut.build(notification, message); context.assertIsSatisfied(); } /** * Tests with multiple recipients. * * @throws Exception * Shouldn't. */ @Test public void testBuildWithMultipleRecipients() throws Exception { notification.setRecipientIds(Arrays.asList(RECIPIENT1_ID, RECIPIENT2_ID)); context.checking(new Expectations() { { // intentionally flip the order in the mapper, since the mapper return order is unpredictable oneOf(peopleMapper).execute( (List<Long>) with(Matchers.allOf(Matchers.hasItem(RECIPIENT1_ID), Matchers .hasItem(RECIPIENT2_ID)))); will(returnValue(Arrays.asList(recipientPerson2, recipientPerson1))); oneOf(emailer).setBcc(with(same(message)), with(equal(RECIPIENT2_EMAIL + "," + RECIPIENT1_EMAIL))); ignoring(emailer).setTextBody(with(any(MimeMessage.class)), with(any(String.class))); ignoring(emailer).setHtmlBody(with(any(MimeMessage.class)), with(any(String.class))); ignoring(emailer).setSubject(with(any(MimeMessage.class)), with(any(String.class))); } }); sut = new TemplateEmailBuilder(emailer, peopleMapper, systemSettingsMapper, null, "", "", ""); sut.build(notification, message); context.assertIsSatisfied(); } /** * Tests the HTML encoding decorator. */ @Test public void testHtmlEncodingDecorator() { final Map<String, String> vars = new HashMap<String, String>(); vars.put("isNull", null); vars.put("needsHelp", "<this & that>"); StrLookup decorated = new StrLookup() { /** * {@inheritDoc} */ @Override public String lookup(final String inKey) { return vars.get(inKey); } }; HtmlEncodingLookup decorator = new HtmlEncodingLookup(decorated); assertNull(decorator.lookup("isNull")); assertEquals("<this & that>", decorator.lookup("needsHelp")); } /** * Tests using system settings. * * @throws Exception * Shouldn't. */ @Test public void testBuildWithSystemSettings() throws Exception { final String template = "$(settings.sitelabel)/$(settings.support.email)/$(settings.support.phone)" + "/$(settings.support.name)" + "/$(settings.support.uniqueid)"; final String expectedText = "SiteLabel/SupportEmailAddress/SupportPhoneNumber/SupportStreamGroupDisplayName" + "/SupportStreamGroupShortName"; setupIgnoreRecipientsExpectations(); context.checking(new Expectations() { { oneOf(emailer).setSubject(with(same(message)), with(equal("S:" + expectedText))); oneOf(emailer).setTextBody(with(same(message)), with(equal("T:" + expectedText))); oneOf(emailer).setHtmlBody(with(same(message)), with(equal("H:" + expectedText))); } }); sut = new TemplateEmailBuilder(emailer, peopleMapper, systemSettingsMapper, null, "S:" + template, "T:" + template, "H:" + template); sut.build(notification, message); context.assertIsSatisfied(); } }