/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* licenses this file to you 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 the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>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.apereo.portal.rendering;
import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.namespace.QName;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;
import org.apereo.portal.layout.IStylesheetUserPreferencesService;
import org.apereo.portal.layout.IStylesheetUserPreferencesService.PreferencesScope;
import org.apereo.portal.layout.IUserLayoutManager;
import org.apereo.portal.layout.dao.IStylesheetDescriptorDao;
import org.apereo.portal.layout.om.ILayoutAttributeDescriptor;
import org.apereo.portal.layout.om.IStylesheetDescriptor;
import org.apereo.portal.spring.spel.IPortalSpELService;
import org.apereo.portal.user.IUserInstanceManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.Expression;
import org.springframework.expression.ParseException;
import org.springframework.web.context.request.WebRequest;
/** JUnit test class for StyleAttributeSource tests with SpEL variables. */
public class StylesheetAttributeSourceForSpELVariablesTest {
private String layoutAttributeName;
private String localEventName;
private String spelExpression;
private String studentId;
private String subscribeId;
private List<ILayoutAttributeDescriptor> layoutAttributeDescriptors;
private PreferencesScope stylesheetPreferencesScope = PreferencesScope.STRUCTURE;
@Mock private HttpServletRequest request;
@Mock private HttpServletResponse response;
@Mock private StartElement startEvent;
@Mock private QName qName;
@Mock private Attribute subscribeIdAttr;
@Mock private IStylesheetDescriptor stylesheetDescriptor;
@Mock private IPortalSpELService portalSpELService;
@Mock private IUserInstanceManager userInstanceManager;
@Mock private IStylesheetDescriptorDao stylesheetDescriptorDao;
@Mock private IStylesheetUserPreferencesService stylesheetUserPreferencesService;
@InjectMocks private MyStylesheetAttributeSource source = new MyStylesheetAttributeSource();
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
this.layoutAttributeName = "studentId";
this.localEventName = "blah";
this.spelExpression = "person.attributeMap['studentId']";
this.studentId = "12345678";
this.subscribeId = "100";
this.layoutAttributeDescriptors = new ArrayList<ILayoutAttributeDescriptor>();
given(
this.stylesheetUserPreferencesService.getStylesheetDescriptor(
this.request, PreferencesScope.STRUCTURE))
.willReturn(this.stylesheetDescriptor);
given(this.stylesheetDescriptor.getLayoutAttributeDescriptors())
.willReturn(this.layoutAttributeDescriptors);
given(this.startEvent.getName()).willReturn(this.qName);
given(this.startEvent.getAttributeByName(IUserLayoutManager.ID_ATTR_NAME))
.willReturn(this.subscribeIdAttr);
given(this.subscribeIdAttr.getValue()).willReturn(this.subscribeId);
given(this.qName.getLocalPart()).willReturn(this.localEventName);
}
@After
public void tearDown() throws Exception {}
@Test
public void
getAdditionalAttributesMethodShouldReturnSpELEvaluatedValueForLayoutAttributeDefault() {
// given
final String layoutAttributeValue =
this.wrapAsSpELExpressionAttributeVariable(this.spelExpression);
this.layoutAttributeWithDefaultValueFoundForName(
this.layoutAttributeName, layoutAttributeValue);
this.layoutAttributeValueNotFoundInUserPreferences(this.layoutAttributeName);
this.spELEvaluatedValueForInputWillBe(this.spelExpression, this.studentId);
// when
final Iterator<Attribute> resultsIterator =
this.source.getAdditionalAttributes(this.request, this.response, this.startEvent);
final List<Attribute> results = this.getResultsUsingIterator(resultsIterator);
// then
this.assertSingleResultWithCorrectValues(results, this.layoutAttributeName, this.studentId);
}
@Test
public void
getAdditionalAttributesMethodShouldReturnSpELEvaluatedValueForUserPreferenceLayoutAttribute() {
// given
final String layoutAttributeValue =
this.wrapAsSpELExpressionAttributeVariable(this.spelExpression);
this.layoutAttributeWithNoDefaultValueFoundForName(this.layoutAttributeName);
this.layoutAttributeValueFoundInUserPreferences(
this.layoutAttributeName, layoutAttributeValue);
this.spELEvaluatedValueForInputWillBe(this.spelExpression, this.studentId);
// when
final Iterator<Attribute> resultsIterator =
this.source.getAdditionalAttributes(this.request, this.response, this.startEvent);
final List<Attribute> results = this.getResultsUsingIterator(resultsIterator);
// then
this.assertSingleResultWithCorrectValues(results, this.layoutAttributeName, this.studentId);
}
@Test
public void getAdditionalAttributesMethodShouldNotDoSpELEvaluationForNonSpELVariable() {
// given
final String layoutAttributeValue =
this.spelExpression; // note that this value is not wrapped in ${ ... }
this.layoutAttributeWithNoDefaultValueFoundForName(this.layoutAttributeName);
this.layoutAttributeValueFoundInUserPreferences(
this.layoutAttributeName, layoutAttributeValue);
// when
final Iterator<Attribute> resultsIterator =
this.source.getAdditionalAttributes(this.request, this.response, this.startEvent);
final List<Attribute> results = this.getResultsUsingIterator(resultsIterator);
// then
verify(this.portalSpELService, never()).parseExpression(any(String.class));
verify(this.portalSpELService, never())
.getValue(any(Expression.class), any(WebRequest.class), eq(String.class));
this.assertSingleResultWithCorrectValues(
results, this.layoutAttributeName, layoutAttributeValue);
}
@Test
public void
getAdditionalAttributesMethodShouldReturnNonSpELEvaluatedLayoutAttributeValueWhenParseExceptionThrown() {
// given
final String layoutAttributeValue =
this.wrapAsSpELExpressionAttributeVariable(this.spelExpression);
this.layoutAttributeWithDefaultValueFoundForName(
this.layoutAttributeName, layoutAttributeValue);
this.layoutAttributeValueNotFoundInUserPreferences(this.layoutAttributeName);
this.spELParsingForInputThrowsParseException(this.spelExpression);
// when
final Iterator<Attribute> resultsIterator =
this.source.getAdditionalAttributes(this.request, this.response, this.startEvent);
final List<Attribute> results = this.getResultsUsingIterator(resultsIterator);
// then
verify(this.portalSpELService, never())
.getValue(any(Expression.class), any(WebRequest.class), eq(String.class));
this.assertSingleResultWithCorrectValues(
results, this.layoutAttributeName, layoutAttributeValue);
}
@Test
public void
getAdditionalAttributesMethodShouldReturnNonSpELEvaluatedLayoutAttributeValueWhenEvaluationExceptionThrown() {
// given
final String layoutAttributeValue =
this.wrapAsSpELExpressionAttributeVariable(this.spelExpression);
this.layoutAttributeWithDefaultValueFoundForName(
this.layoutAttributeName, layoutAttributeValue);
this.layoutAttributeValueNotFoundInUserPreferences(this.layoutAttributeName);
this.spELEvaluationForInputThrowsEvaluationException(this.spelExpression);
// when
final Iterator<Attribute> resultsIterator =
this.source.getAdditionalAttributes(this.request, this.response, this.startEvent);
final List<Attribute> results = this.getResultsUsingIterator(resultsIterator);
// then
this.assertSingleResultWithCorrectValues(
results, this.layoutAttributeName, layoutAttributeValue);
}
private void layoutAttributeValueFoundInUserPreferences(
final String layoutAttributeName, final String value) {
given(
this.stylesheetUserPreferencesService.getLayoutAttribute(
this.request,
this.stylesheetPreferencesScope,
this.subscribeId,
layoutAttributeName))
.willReturn(value);
}
private void layoutAttributeValueNotFoundInUserPreferences(final String layoutAttributeName) {
given(
this.stylesheetUserPreferencesService.getLayoutAttribute(
this.request,
this.stylesheetPreferencesScope,
this.subscribeId,
layoutAttributeName))
.willReturn(null);
}
private void layoutAttributeWithDefaultValueFoundForName(
final String layoutAttributeName, final String defaultValue) {
this.layoutAttributeFoundForName(layoutAttributeName, defaultValue);
}
private void layoutAttributeWithNoDefaultValueFoundForName(final String layoutAttributeName) {
this.layoutAttributeFoundForName(layoutAttributeName, null);
}
private void layoutAttributeFoundForName(
final String layoutAttributeName, final String defaultValue) {
final ILayoutAttributeDescriptor layoutAttributeDescriptor =
mock(ILayoutAttributeDescriptor.class);
this.layoutAttributeDescriptorReturnsTargetElementNames(
layoutAttributeDescriptor, this.localEventName);
this.layoutAttributeDescriptors.add(layoutAttributeDescriptor);
given(layoutAttributeDescriptor.getName()).willReturn(layoutAttributeName);
given(layoutAttributeDescriptor.getDefaultValue()).willReturn(defaultValue);
}
private void layoutAttributeDescriptorReturnsTargetElementNames(
ILayoutAttributeDescriptor descriptor, final String... strings) {
final Set<String> results = new HashSet<String>(strings.length);
for (int i = 0; i < strings.length; i++) {
results.add(strings[i]);
}
given(descriptor.getTargetElementNames()).willReturn(results);
}
private void spELEvaluatedValueForInputWillBe(final String input, final String value) {
final Expression expression = mock(Expression.class);
given(this.portalSpELService.parseExpression(input)).willReturn(expression);
given(
this.portalSpELService.getValue(
eq(expression), any(WebRequest.class), eq(String.class)))
.willReturn(value);
}
private void spELParsingForInputThrowsParseException(final String input) {
given(this.portalSpELService.parseExpression(input))
.willThrow(new ParseException(0, input));
}
private void spELEvaluationForInputThrowsEvaluationException(final String input) {
final Expression expression = mock(Expression.class);
given(this.portalSpELService.parseExpression(input)).willReturn(expression);
given(
this.portalSpELService.getValue(
eq(expression), any(WebRequest.class), eq(String.class)))
.willThrow(new EvaluationException(input));
}
private List<Attribute> getResultsUsingIterator(final Iterator<Attribute> iterator) {
final List<Attribute> results = new ArrayList<Attribute>();
while (iterator.hasNext()) {
results.add(iterator.next());
}
return results;
}
private void assertSingleResultWithCorrectValues(
List<Attribute> results, final String name, final String value) {
assertEquals(1, results.size());
assertEquals(name, results.get(0).getName().getLocalPart());
assertEquals(value, results.get(0).getValue());
}
private String wrapAsSpELExpressionAttributeVariable(final String value) {
return "${" + value + "}";
}
class MyStylesheetAttributeSource extends StylesheetAttributeSource {
private final Logger logger = LoggerFactory.getLogger(MyStylesheetAttributeSource.class);
@Override
public PreferencesScope getStylesheetPreferencesScope(HttpServletRequest request) {
return stylesheetPreferencesScope;
}
@Override
public Logger getLogger() {
return logger;
}
}
}