Skip to content
This repository has been archived by the owner on Dec 11, 2018. It is now read-only.

Javier Ruiz Test #43

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ build/
nbbuild/
dist/
nbdist/
.nb-gradle/
.nb-gradle/
/bin/
15 changes: 15 additions & 0 deletions src/main/java/com/scmspain/controller/TweetController.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package com.scmspain.controller;

import com.scmspain.controller.command.DiscardTweetCommand;
import com.scmspain.controller.command.PublishTweetCommand;
import com.scmspain.entities.Tweet;
import com.scmspain.services.TweetService;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy;

import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.OK;

@RestController
public class TweetController {
Expand All @@ -29,6 +32,18 @@ public void publishTweet(@RequestBody PublishTweetCommand publishTweetCommand) {
this.tweetService.publishTweet(publishTweetCommand.getPublisher(), publishTweetCommand.getTweet());
}


@PostMapping("/discarded")
@ResponseStatus(OK)
public void discardTweet(@RequestBody DiscardTweetCommand discardTweetCommand) {
this.tweetService.discardTweet(new Long(discardTweetCommand.getTweet()));
}

@GetMapping("/discarded")
public List<Tweet> listDiscardedTweets() {
return this.tweetService.listDiscardedTweets();
}

@ExceptionHandler(IllegalArgumentException.class)
@ResponseStatus(BAD_REQUEST)
@ResponseBody
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.scmspain.controller.command;

public class DiscardTweetCommand {

private long tweet;

public long getTweet() {
return tweet;
}

public void setTweet(long tweet) {
this.tweet = tweet;
}

}
36 changes: 33 additions & 3 deletions src/main/java/com/scmspain/entities/Tweet.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,48 @@
package com.scmspain.entities;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

import com.fasterxml.jackson.annotation.JsonFormat;

@Entity
public class Tweet {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String publisher;
@Column(nullable = false, length = 140)
@Column(nullable = false, length = 1000)
private String tweet;
@Column (nullable=true)
private Long pre2015MigrationStatus = 0L;

public Tweet() {
@Column (nullable=true)
@Enumerated(EnumType.STRING)
private TweetStatus status;

@Column (nullable=true)
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
private Date discardDate;

public Tweet() {
}

public Long getId() {
public Date getDiscardDate() {
return discardDate;
}

public void setDiscardDate(Date discardDate) {
this.discardDate = discardDate;
}

public Long getId() {
return id;
}

Expand Down Expand Up @@ -52,4 +74,12 @@ public void setPre2015MigrationStatus(Long pre2015MigrationStatus) {
this.pre2015MigrationStatus = pre2015MigrationStatus;
}

public TweetStatus getStatus() {
return status;
}

public void setStatus(TweetStatus status) {
this.status = status;
}

}
6 changes: 6 additions & 0 deletions src/main/java/com/scmspain/entities/TweetStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.scmspain.entities;

public enum TweetStatus {
ACTIVE,
DISCARDED
}
64 changes: 62 additions & 2 deletions src/main/java/com/scmspain/services/TweetService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.scmspain.services;

import com.scmspain.entities.Tweet;
import com.scmspain.entities.TweetStatus;

import org.springframework.boot.actuate.metrics.writer.Delta;
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
import org.springframework.stereotype.Service;
Expand All @@ -9,6 +11,7 @@
import javax.persistence.TypedQuery;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
Expand All @@ -29,17 +32,62 @@ public TweetService(EntityManager entityManager, MetricWriter metricWriter) {
Result - recovered Tweet
*/
public void publishTweet(String publisher, String text) {
if (publisher != null && publisher.length() > 0 && text != null && text.length() > 0 && text.length() < 140) {


if (publisher != null && publisher.length() > 0 && text != null && text.length() > 0 && getTextLengthWithoutLinks(text) < 140) {

Tweet tweet = new Tweet();
tweet.setTweet(text);
tweet.setPublisher(publisher);


this.metricWriter.increment(new Delta<Number>("published-tweets", 1));
this.entityManager.persist(tweet);
} else {
throw new IllegalArgumentException("Tweet must not be greater than 140 characters");
}
}

public void discardTweet(Long id)
{
Tweet tweet = this.entityManager.find(Tweet.class, id);
if (tweet!=null)
{
tweet.setStatus(TweetStatus.DISCARDED);
tweet.setDiscardDate(new Date());
this .entityManager.persist(tweet);
}

}


private int getTextLengthWithoutLinks(String text)
{
return (text.length() - obtainPatternsLength(text,"http://"," ") - obtainPatternsLength(text,"https://"," "));

}


private int obtainPatternsLength(String text, String startWithStr, String endsWithStr)
{
int patternLength = 0;
int ini =0;
int end=0;

while ((ini = text.indexOf(startWithStr,end))!=-1)
{

end = text.indexOf(endsWithStr,ini);
if (end==-1) end=text.length();

patternLength+=(end-ini+1);

}

return patternLength;

}


/**
Recover tweet from repository
Expand All @@ -58,11 +106,23 @@ public Tweet getTweet(Long id) {
public List<Tweet> listAllTweets() {
List<Tweet> result = new ArrayList<Tweet>();
this.metricWriter.increment(new Delta<Number>("times-queried-tweets", 1));
TypedQuery<Long> query = this.entityManager.createQuery("SELECT id FROM Tweet AS tweetId WHERE pre2015MigrationStatus<>99 ORDER BY id DESC", Long.class);
TypedQuery<Long> query = this.entityManager.createQuery("SELECT id FROM Tweet AS tweetId WHERE pre2015MigrationStatus<>99 and (status is null or status<>'DISCARDED') ORDER BY id DESC", Long.class);
List<Long> ids = query.getResultList();
for (Long id : ids) {
result.add(getTweet(id));
}
return result;
}

public List<Tweet> listDiscardedTweets() {
List<Tweet> result = new ArrayList<Tweet>();
this.metricWriter.increment(new Delta<Number>("times-queried-discarded-tweets", 1));
TypedQuery<Long> query = this.entityManager.createQuery("SELECT id FROM Tweet AS tweetId WHERE pre2015MigrationStatus<>99 and status ='DISCARDED' ORDER BY discardDate DESC", Long.class);
List<Long> ids = query.getResultList();
for (Long id : ids) {
result.add(getTweet(id));
}
return result;
}

}
39 changes: 38 additions & 1 deletion src/test/java/com/scmspain/controller/TweetControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,27 @@ public void shouldReturn200WhenInsertingAValidTweet() throws Exception {
.andExpect(status().is(201));
}


@Test
public void shouldReturn400WhenInsertingAnInvalidTweet() throws Exception {
mockMvc.perform(newTweet("Schibsted Spain", "We are Schibsted Spain (look at our home page http://www.schibsted.es/), we own Vibbo, InfoJobs, fotocasa, coches.net and milanuncios. Welcome!"))
mockMvc.perform(newTweet("Schibsted Spain", "We are Schibsted Spain (look at our home page , we own Vibbo, InfoJobs, fotocasa, coches.net, Vibbo, InfoJobs, fotocasa, coches.net,Vibbo, InfoJobs, fotocasa, coches.net and milanuncios. Welcome!"))
.andExpect(status().is(400));
}

@Test
public void shouldReturn200WhenInsertingValidTweetWithLinks() throws Exception {
mockMvc.perform(newTweet("Schibsted Spain", "We are Schibsted Spain (look at our home page http://www.schibsted.es/), we own Vibbo, InfoJobs, fotocasa, coches.net and milanuncios. Welcome!"))
.andExpect(status().is(201));
}

@Test
public void shouldReturn200WhenDiscardingTweet() throws Exception {
mockMvc.perform(newTweet("Prospect", "Breaking the law"))
.andExpect(status().is(201));

mockMvc.perform(discardTweet(new Long(1).longValue())).andExpect(status().is(200));
}

@Test
public void shouldReturnAllPublishedTweets() throws Exception {
mockMvc.perform(newTweet("Yo", "How are you?"))
Expand All @@ -60,10 +75,32 @@ public void shouldReturnAllPublishedTweets() throws Exception {
assertThat(new ObjectMapper().readValue(content, List.class).size()).isEqualTo(1);
}

@Test
public void shouldReturnAllDiscardedTweets() throws Exception {
mockMvc.perform(newTweet("Yo", "How are you?"))
.andExpect(status().is(201));

mockMvc.perform(discardTweet(1))
.andExpect(status().is(200));


MvcResult getResult = mockMvc.perform(get("/discarded"))
.andExpect(status().is(200))
.andReturn();

String content = getResult.getResponse().getContentAsString();
assertThat(new ObjectMapper().readValue(content, List.class).size()).isEqualTo(1);
}
private MockHttpServletRequestBuilder newTweet(String publisher, String tweet) {
return post("/tweet")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(format("{\"publisher\": \"%s\", \"tweet\": \"%s\"}", publisher, tweet));
}

private MockHttpServletRequestBuilder discardTweet(long id) {
return post("/discarded")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(format("{ \"tweet\": %d}", id));
}

}
27 changes: 27 additions & 0 deletions src/test/java/com/scmspain/services/TweetServiceTest.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package com.scmspain.services;

import com.scmspain.entities.Tweet;
import com.scmspain.entities.TweetStatus;

import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.actuate.metrics.writer.MetricWriter;

import javax.persistence.EntityManager;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class TweetServiceTest {
private EntityManager entityManager;
Expand All @@ -30,7 +34,30 @@ public void shouldInsertANewTweet() throws Exception {

verify(entityManager).persist(any(Tweet.class));
}


@Test
public void shouldDiscardATweet() throws Exception {

tweetService.publishTweet("Guybrush Threepwood", "I am Guybrush Threepwood, mighty pirate.");
verify(entityManager).persist(any(Tweet.class));

Long id = new Long(1);

tweetService.discardTweet(id);
verify(entityManager).persist(any(Tweet.class));
verify(entityManager).find(Tweet.class,id);


}

@Test
public void shouldInsertAValidTweetWithExceededSizeByLinks() throws Exception {
tweetService.publishTweet("Pirate","We are Schibsted Spain (look at our home page http://www.schibsted.es/), we own Vibbo, InfoJobs, fotocasa, coches.net and milanuncios. Welcome!");

verify(entityManager).persist(any(Tweet.class));
}

@Test(expected = IllegalArgumentException.class)
public void shouldThrowAnExceptionWhenTweetLengthIsInvalid() throws Exception {
tweetService.publishTweet("Pirate", "LeChuck? He's the guy that went to the Governor's for dinner and never wanted to leave. He fell for her in a big way, but she told him to drop dead. So he did. Then things really got ugly.");
Expand Down