/*
* Copyright (c) 2009 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.service.restlets;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
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;
import org.restlet.Context;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.resource.Representation;
import org.restlet.resource.ResourceException;
import org.restlet.resource.Variant;
import org.eurekastreams.server.domain.Person;
import org.eurekastreams.server.domain.Recommendation;
import org.eurekastreams.server.persistence.PersonMapper;
import org.eurekastreams.server.persistence.RecommendationMapper;
/**
* Test class for the RecommendationsCollectionResource.
*/
public class RecommendationsCollectionResourceTest
{
/**
* Subject under test.
*/
RecommendationsCollectionResource sut;
/**
* List of people expected to be returned from the search for users by
* opensocial id.
*/
private List<Person> people = new ArrayList<Person>();
/**
* Context for building mock objects.
*/
private final Mockery context = new JUnit4Mockery()
{
{
setImposteriser(ClassImposteriser.INSTANCE);
}
};
/**
* Mocked mapper for retrieving recommendations.
*/
private RecommendationMapper recoMapper = context.mock(RecommendationMapper.class);
/**
* Mocked mapper for retrieving author information.
*/
private PersonMapper personMapper = context.mock(PersonMapper.class);
/**
* Adapter mock for the Response object.
*/
private ResponseAdapter responseAdapter = context.mock(ResponseAdapter.class);
/**
* An Open Social id to use for testing. Arbitrary.
*/
private static final String SUBJECT_OPENSOCIAL_ID = UUID.randomUUID().toString();
/**
* Another Open Social id. Arbitrary.
*/
private static final String AUTHOR_OPENSOCIAL_ID = UUID.randomUUID().toString();
/**
* An arbitrary date/time at which the recommendations where made.
*/
private static final Date RECO_DATE = new Date();
/**
* Set up the SUT.
*/
@Before
public void setup()
{
Context restContext = context.mock(Context.class);
final Request request = context.mock(Request.class);
Response response = context.mock(Response.class);
final Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put("openSocialId", SUBJECT_OPENSOCIAL_ID);
attributes.put("maxResults", "5");
buildPeople();
context.checking(new Expectations()
{
{
atLeast(2).of(request).getAttributes();
will(returnValue(attributes));
}
});
sut = new RecommendationsCollectionResource();
sut.init(restContext, request, response);
sut.setRecommendationMapper(recoMapper);
sut.setPersonMapper(personMapper);
sut.setAdaptedResponse(responseAdapter);
}
/**
* Test the GET call.
*
* @throws ResourceException
* should not occur.
* @throws IOException
* should not occur
*/
@Test
public void represent() throws ResourceException, IOException
{
Variant variant = context.mock(Variant.class);
final List<Recommendation> recos = buildRecommendationList();
final List<String> openSocialIds = new ArrayList<String>();
openSocialIds.add(SUBJECT_OPENSOCIAL_ID);
openSocialIds.add(AUTHOR_OPENSOCIAL_ID);
openSocialIds.add(AUTHOR_OPENSOCIAL_ID);
openSocialIds.add(AUTHOR_OPENSOCIAL_ID);
context.checking(new Expectations()
{
{
oneOf(recoMapper).findBySubjectOpenSocialId(SUBJECT_OPENSOCIAL_ID, 5);
will(returnValue(recos));
allowing(personMapper).findPeopleByOpenSocialIds(openSocialIds);
will(returnValue(people));
}
});
Representation actual = sut.represent(variant);
assertEquals(MediaType.APPLICATION_JSON, actual.getMediaType());
JSONObject json = JSONObject.fromObject(actual.getText());
JSONArray recommendations = json.getJSONArray(RecommendationsCollectionResource.RECOMMENDATIONS_KEY);
assertEquals(recos.size(), recommendations.size());
context.assertIsSatisfied();
}
/**
* Utility method to set up some recommendations.
*
* @return a list of recommendations with expectations set up.
*/
private List<Recommendation> buildRecommendationList()
{
final List<Recommendation> list = new ArrayList<Recommendation>();
context.checking(new Expectations()
{
{
setupRecommendation(1, "reco1");
setupRecommendation(2, "reco2");
setupRecommendation(3, "reco3");
}
private void setupRecommendation(final long id, final String recoName)
{
final Recommendation reco = context.mock(Recommendation.class, recoName);
list.add(reco);
allowing(reco).getId();
will(returnValue(id));
allowing(reco).getSubjectOpenSocialId();
will(returnValue(SUBJECT_OPENSOCIAL_ID));
allowing(reco).getAuthorOpenSocialId();
will(returnValue(AUTHOR_OPENSOCIAL_ID));
allowing(reco).getDate();
will(returnValue(RECO_DATE));
allowing(reco).getText();
will(returnValue(recoName));
}
});
return list;
}
/**
* Test the POST functionality.
* @throws IOException not expected
* @throws ResourceException not expected
*/
@Test
public void acceptRepresentation() throws IOException, ResourceException
{
final Representation entity = context.mock(Representation.class);
final String json = buildJSONRecommendation();
final List<String> openSocialIds = new ArrayList<String>();
openSocialIds.add(AUTHOR_OPENSOCIAL_ID);
openSocialIds.add(SUBJECT_OPENSOCIAL_ID);
context.checking(new Expectations()
{
{
// note: this really needs to be called only one time
oneOf(entity).getText();
will(returnValue(json));
oneOf(recoMapper).insert(with(any(Recommendation.class)));
allowing(personMapper).findPeopleByOpenSocialIds(openSocialIds);
will(returnValue(people));
oneOf(responseAdapter).setEntity(buildJSONResponse(),
MediaType.APPLICATION_JSON);
}
});
sut.acceptRepresentation(entity);
context.assertIsSatisfied();
}
/**
* Populate a global collection of people to be used in tests.
*/
private void buildPeople()
{
Person authorPerson = new Person();
authorPerson.setOpenSocialId(AUTHOR_OPENSOCIAL_ID);
Person subjectPerson = new Person();
subjectPerson.setOpenSocialId(SUBJECT_OPENSOCIAL_ID);
people.add(authorPerson);
people.add(subjectPerson);
}
/**
* Assemble a JSON string that represents a test response from the Restlet.
* @return - string representation of a JSON Recommendation.
*/
private String buildJSONResponse()
{
JSONObject json = new JSONObject();
JSONObject jsonAuthor = new JSONObject();
JSONObject jsonSubject = new JSONObject();
jsonAuthor.put(RecommendationsResource.ID_KEY, AUTHOR_OPENSOCIAL_ID);
jsonAuthor.put(RecommendationsResource.AUTHOR_NAME_KEY, "null null");
jsonAuthor.put(RecommendationsResource.PERSON_IMAGE_KEY, "/style/images/noPhoto50.png");
jsonSubject.put(RecommendationsResource.ID_KEY, SUBJECT_OPENSOCIAL_ID);
jsonSubject.put(RecommendationsResource.AUTHOR_NAME_KEY, "null null");
jsonSubject.put(RecommendationsResource.PERSON_IMAGE_KEY, "/style/images/noPhoto50.png");
json.put(RecommendationsResource.ID_KEY, 0);
json.put(RecommendationsResource.AUTHOR_KEY, jsonAuthor);
json.put(RecommendationsResource.SUBJECT_KEY, jsonSubject);
SimpleDateFormat formater = new SimpleDateFormat(RecommendationsResource.DATE_FORMAT);
json.put(RecommendationsResource.DATE_KEY, formater.format(RECO_DATE));
json.put(RecommendationsResource.TEXT_KEY, "recommendation text");
return json.toString();
}
/**
* Utility method to build a JSON string representing a Recommendation being posted to the collection.
* @return JSON string
*/
private String buildJSONRecommendation()
{
JSONObject json = new JSONObject();
JSONObject jsonAuthor = new JSONObject();
JSONObject jsonSubject = new JSONObject();
jsonAuthor.put(RecommendationsResource.ID_KEY, AUTHOR_OPENSOCIAL_ID);
jsonAuthor.put(RecommendationsResource.AUTHOR_NAME_KEY, "Joe Smith");
jsonAuthor.put(RecommendationsResource.PERSON_IMAGE_KEY, "/image/image.png");
jsonSubject.put(RecommendationsResource.ID_KEY, SUBJECT_OPENSOCIAL_ID);
jsonSubject.put(RecommendationsResource.AUTHOR_NAME_KEY, "John Smith");
jsonSubject.put(RecommendationsResource.PERSON_IMAGE_KEY, "/image/image.png");
json.put(RecommendationsResource.ID_KEY, "34");
json.put(RecommendationsResource.AUTHOR_KEY, jsonAuthor);
json.put(RecommendationsResource.SUBJECT_KEY, jsonSubject);
SimpleDateFormat formater = new SimpleDateFormat(RecommendationsResource.DATE_FORMAT);
json.put(RecommendationsResource.DATE_KEY, formater.format(RECO_DATE));
json.put(RecommendationsResource.TEXT_KEY, "recommendation text");
return json.toString();
}
}