package com.collabinate.server.resources;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.junit.Test;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.data.Conditions;
import org.restlet.data.MediaType;
import org.restlet.data.Method;
import org.restlet.data.Status;
import org.restlet.data.Tag;
import com.collabinate.server.activitystreams.Activity;
import com.collabinate.server.activitystreams.ActivityStreamsCollection;
import com.collabinate.server.activitystreams.ActivityStreamsObject;
import com.google.gson.JsonParser;
/**
* Tests for the Stream Resource
*
* @author mafuba
*
*/
public class StreamResourceTest extends GraphResourceTest
{
@Test
public void get_empty_stream_should_return_200()
{
assertEquals(Status.SUCCESS_OK, get().getStatus());
}
@Test
public void get_should_return_json_content_type()
{
assertEquals(MediaType.APPLICATION_JSON,
get().getEntity().getMediaType());
}
@Test
public void get_response_should_contain_etag_header()
{
assertTrue(null != get().getEntity().getTag());
}
@Test
public void etag_should_change_when_stream_changes()
{
Tag tag1 = get().getEntity().getTag();
post("TEST", MediaType.TEXT_PLAIN);
Tag tag2 = get().getEntity().getTag();
assertNotEquals(tag1, tag2);
}
@Test
public void matching_etag_should_return_304()
{
Tag etag = get().getEntity().getTag();
Request request = getRequest(Method.GET, null);
Conditions conditions = new Conditions();
conditions.getNoneMatch().add(etag);
request.setConditions(conditions);
assertEquals(Status.REDIRECTION_NOT_MODIFIED,
getResponse(request).getStatus());
}
@Test
public void non_matching_etag_should_return_200()
{
Request request = getRequest(Method.GET, null);
Conditions conditions = new Conditions();
conditions.getNoneMatch().add(new Tag("abc"));
request.setConditions(conditions);
assertEquals(Status.SUCCESS_OK, getResponse(request).getStatus());
}
@Test
public void item_added_to_stream_should_return_201()
{
assertEquals(Status.SUCCESS_CREATED, post().getStatus());
}
@Test
public void item_added_to_stream_should_create_and_return_child_location()
{
assertEquals(
getRequest(Method.POST, null).getResourceRef().getPath() + "/",
post().getLocationRef().getParentRef().getPath());
}
@Test
public void item_added_to_stream_should_have_entity_in_post_response_body()
{
String entityBody = "TEST";
Response response = post(entityBody, MediaType.TEXT_PLAIN);
assertThat(response.getEntityAsText(), containsString(entityBody));
}
@Test
public void post_response_body_should_be_json()
{
String entityBody = "TEST,";
Response response = post(entityBody, MediaType.TEXT_PLAIN);
new JsonParser().parse(response.getEntityAsText());
}
@Test
public void post_response_body_should_contain_added_fields()
{
String entityBody = "TEST";
Response response = post(entityBody, MediaType.TEXT_PLAIN);
assertThat(response.getEntityAsText(), containsString("\"id\""));
}
@Test
public void stream_should_be_json_object()
{
post("TEST", MediaType.TEXT_PLAIN);
// parser will throw if result is not json
new JsonParser().parse(get().getEntityAsText());
}
@Test
public void item_added_to_stream_should_appear_in_stream()
{
String entityBody = "TEST";
post(entityBody, MediaType.TEXT_PLAIN);
assertThat(get().getEntityAsText(), containsString(entityBody));
}
@Test
public void activity_should_not_use_given_id()
{
String entityBody = "{\"id\":\"TEST\"}";
post(entityBody, MediaType.TEXT_PLAIN);
ActivityStreamsCollection stream =
new ActivityStreamsCollection(get().getEntityAsText());
assertNotEquals("TEST", stream.get(0).getId());
}
@Test
public void individual_activity_should_be_retrievable_via_generated_id()
{
String entityBody = "{\"id\":\"test\",\"actor\":{\"id\":\"foo\"}}";
Activity posted = new Activity(
post(entityBody, MediaType.TEXT_PLAIN).getEntityAsText());
Request request = new Request(Method.GET,
"riap://application/1/tenant/entities/entity/stream/"
+ posted.getId());
Activity activity = new Activity(
component.handle(request).getEntityAsText());
assertEquals("foo", activity.getActor().getId());
}
@Test
public void original_id_should_be_preserved()
{
String entityBody = "{\"id\":\"original\",\"actor\":{\"id\":\"foo\"}}";
Activity posted = new Activity(
post(entityBody, MediaType.TEXT_PLAIN).getEntityAsText());
assertEquals("original", posted.getCollabinateValue("originalId"));
}
@Test
public void posted_raw_text_should_have_id_in_activity_when_retrieved()
{
post("test", MediaType.TEXT_PLAIN);
ActivityStreamsCollection stream =
new ActivityStreamsCollection(get().getEntityAsText());
assertNotNull(stream.get(0).getId());
}
@Test
public void activity_stream_date_in_post_should_be_used_in_stream()
{
DateTime dateTime = new DateTime(1977, 5, 13, 5, 13, DateTimeZone.UTC);
Activity activity = new Activity();
activity.setPublished(dateTime);
String entityBody = activity.toString();
post(entityBody, MediaType.APPLICATION_JSON);
ActivityStreamsCollection stream =
new ActivityStreamsCollection(get().getEntityAsText());
assertEquals(dateTime, stream.get(0).getPublished());
}
@Test
public void activities_should_appear_in_correct_date_order()
{
DateTime dateTime1 = new DateTime(1977, 5, 13, 5, 13, DateTimeZone.UTC);
Activity activity1 = new Activity();
activity1.setPublished(dateTime1);
DateTime dateTime2 = new DateTime(1973, 6, 28, 6, 28, DateTimeZone.UTC);
Activity activity2 = new Activity();
activity2.setPublished(dateTime2);
post(activity1.toString(), MediaType.APPLICATION_JSON);
post(activity2.toString(), MediaType.APPLICATION_JSON);
ActivityStreamsCollection stream =
new ActivityStreamsCollection(get().getEntityAsText());
assertEquals(dateTime1, stream.get(0).getPublished());
}
@Test
public void collection_should_include_total_items_property()
{
assertThat(get().getEntityAsText(), containsString("totalItems"));
}
@Test
public void collection_should_include_zero_count_for_empty_stream()
{
ActivityStreamsCollection stream =
new ActivityStreamsCollection(get().getEntityAsText());
assertEquals(0, stream.getTotalItems());
}
@Test
public void collection_should_include_count_that_matches_stream()
{
post();
post();
ActivityStreamsCollection stream =
new ActivityStreamsCollection(get().getEntityAsText());
assertEquals(2, stream.getTotalItems());
}
@Test
public void collection_count_should_account_for_deleted_activities()
{
post();
post();
Activity deleted = new Activity(post().getEntityAsText());
Request request = new Request(Method.DELETE,
"riap://application/1/tenant/entities/entity/stream/"
+ deleted.getId());
component.handle(request);
ActivityStreamsCollection stream =
new ActivityStreamsCollection(get().getEntityAsText());
assertEquals(2, stream.getTotalItems());
}
@Test
public void liked_item_in_stream_should_contain_user_like_indication()
{
// add activity to the stream of entity and get the ID
String activityId = (new Activity(post().getEntityAsText())).getId();
// like the entity
Request request = new Request(Method.PUT,
"riap://application/1/tenant/users/user/likes/entity/"
+ activityId);
component.handle(request);
ActivityStreamsCollection stream =
new ActivityStreamsCollection(get("?userLiked=user")
.getEntityAsText());
assertNotNull(stream.get(0).getCollabinateValue("likedByUser"));
}
@Test
public void unliked_item_in_stream_should_not_contain_user_like_indication()
{
// add activity to the stream of entity and get the ID
String activityId = (new Activity(post().getEntityAsText())).getId();
// like the entity
Request request = new Request(Method.PUT,
"riap://application/1/tenant/users/user/likes/entity/"
+ activityId);
component.handle(request);
// unlike the entity
request = new Request(Method.DELETE,
"riap://application/1/tenant/users/user/likes/entity/"
+ activityId);
component.handle(request);
ActivityStreamsCollection stream =
new ActivityStreamsCollection(get("?userLiked=user")
.getEntityAsText());
assertNull(stream.get(0).getCollabinateValue("likedByUser"));
}
@Test
public void comments_param_should_return_the_correct_comments()
{
// create an activity that has comments
ActivityStreamsCollection comments = new ActivityStreamsCollection();
comments.add(new ActivityStreamsObject("comment1"));
comments.add(new ActivityStreamsObject("comment2"));
comments.add(new ActivityStreamsObject("comment3"));
Activity activity = new Activity();
activity.setReplies(comments);
// post the activity to the stream
post(activity.toString(), MediaType.TEXT_PLAIN);
// ensure comments param works as intended
ActivityStreamsCollection activities =
new ActivityStreamsCollection(
get("?comments=2").getEntityAsText());
activity = new Activity(activities.get(0).toString());
assertEquals(3, activity.getReplies().getTotalItems());
assertEquals(2, activity.getReplies().getItems().size());
assertEquals("comment3", activity.getReplies().get(0).getContent());
assertEquals("comment2", activity.getReplies().get(1).getContent());
}
@Test
public void likes_param_should_return_the_correct_likes()
{
// create an activity that has likes in it
ActivityStreamsObject actor1 = new ActivityStreamsObject();
actor1.setId("user1");
Activity like1 = new Activity();
like1.setActor(actor1);
ActivityStreamsObject actor2 = new ActivityStreamsObject();
actor2.setId("user2");
Activity like2 = new Activity();
like2.setActor(actor2);
ActivityStreamsObject actor3 = new ActivityStreamsObject();
actor3.setId("user3");
Activity like3 = new Activity();
like3.setActor(actor3);
ActivityStreamsCollection likes = new ActivityStreamsCollection();
likes.add(like1);
likes.add(like2);
likes.add(like3);
Activity activity = new Activity();
activity.setLikes(likes);
// post the activity to the stream
post(activity.toString(), MediaType.TEXT_PLAIN);
// ensure likes param works as intended
ActivityStreamsCollection activities =
new ActivityStreamsCollection(
get("?likes=2").getEntityAsText());
activity = new Activity(activities.get(0).toString());
assertEquals(3, activity.getLikes().getTotalItems());
assertEquals(2, activity.getLikes().getItems().size());
assertThat(activity.getLikes().get(0).toString(),
containsString("user"));
}
@Test
public void existing_comments_on_activity_should_be_added_to_its_comments()
{
// create an activity that has a comment
String commentContent = "random test comment";
ActivityStreamsObject comment =
new ActivityStreamsObject(commentContent);
ActivityStreamsCollection comments = new ActivityStreamsCollection();
comments.add(comment);
Activity activity = new Activity();
activity.setReplies(comments);
// post the activity to the stream
Activity posted = new Activity(
post(activity.toString(), MediaType.TEXT_PLAIN)
.getEntityAsText());
String postedId = posted.getId();
// ensure comment exists as addressable item
Request request = new Request(Method.GET,
"riap://application/1/tenant/entities/entity/stream/"
+ postedId + "/comments");
comments = new ActivityStreamsCollection(
component.handle(request).getEntityAsText());
assertEquals(commentContent, comments.get(0).getContent());
assertNotNull(comments.get(0).getId());
}
@Test
public void ignore_comments_param_should_prevent_existing_comment_addition()
{
// create an activity that has a comment
String commentContent = "random test comment";
ActivityStreamsObject comment =
new ActivityStreamsObject(commentContent);
ActivityStreamsCollection comments = new ActivityStreamsCollection();
comments.add(comment);
Activity activity = new Activity();
activity.setReplies(comments);
// post the activity to the stream using ignore comments param
Activity posted = new Activity(
post(activity.toString(),
MediaType.TEXT_PLAIN,
"?ignoreComments=true")
.getEntityAsText());
String postedId = posted.getId();
// ensure comment was not added
Request request = new Request(Method.GET,
"riap://application/1/tenant/entities/entity/stream/"
+ postedId + "/comments");
comments = new ActivityStreamsCollection(
component.handle(request).getEntityAsText());
assertEquals(0, comments.getTotalItems());;
}
@Test
public void existing_likes_on_activity_should_be_added_to_its_likes()
{
// create an activity that has a like in it by a particular user
ActivityStreamsObject actor = new ActivityStreamsObject();
actor.setId("user");
Activity like = new Activity();
like.setActor(actor);
ActivityStreamsCollection likes = new ActivityStreamsCollection();
likes.add(like);
Activity activity = new Activity();
activity.setLikes(likes);
// post the activity to the stream
Activity posted = new Activity(
post(activity.toString(), MediaType.TEXT_PLAIN)
.getEntityAsText());
String postedId = posted.getId();
// ensure like exists as addressable item
Request request = new Request(Method.GET,
"riap://application/1/tenant/entities/entity/stream/"
+ postedId + "/likes");
likes = new ActivityStreamsCollection(
component.handle(request).getEntityAsText());
like = new Activity(likes.get(0).toString());
assertEquals(actor.getId(), like.getActor().getId());
}
@Test
public void ignore_likes_param_should_prevent_existing_like_addition()
{
// create an activity that has a like in it by a particular user
ActivityStreamsObject actor = new ActivityStreamsObject();
actor.setId("user");
Activity like = new Activity();
like.setActor(actor);
ActivityStreamsCollection likes = new ActivityStreamsCollection();
likes.add(like);
Activity activity = new Activity();
activity.setLikes(likes);
// post the activity to the stream using ignore likes param
Activity posted = new Activity(
post(activity.toString(),
MediaType.TEXT_PLAIN,
"?ignoreLikes=true")
.getEntityAsText());
String postedId = posted.getId();
// ensure like was not added
Request request = new Request(Method.GET,
"riap://application/1/tenant/entities/entity/stream/"
+ postedId + "/likes");
likes = new ActivityStreamsCollection(
component.handle(request).getEntityAsText());
assertEquals(0, likes.getTotalItems());
}
@Override
protected String getResourcePath()
{
return "/1/tenant/entities/entity/stream";
}
}