Initial commit
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
.gradle
|
||||
.idea
|
||||
build
|
||||
gradle
|
||||
gradlew
|
||||
gradlew.bat
|
||||
72
README.md
Normal file
72
README.md
Normal file
@@ -0,0 +1,72 @@
|
||||
|
||||
<h1>ConsoleTwitter</h1>
|
||||
|
||||
Implementation of a console-based social networking application (similar to Twitter) satisfying the scenarios below.
|
||||
|
||||
<h2>Scenarios</h2>
|
||||
|
||||
Posting: Alice can publish messages to a personal timeline
|
||||
|
||||
```
|
||||
> Alice -> I love the weather today
|
||||
> Bob -> Damn! We lost!
|
||||
> Bob -> Good game though.
|
||||
```
|
||||
Reading: Bob can view Alice’s timeline
|
||||
|
||||
```
|
||||
> Alice
|
||||
I love the weather today (5 minutes ago)
|
||||
> Bob
|
||||
Good game though. (1 minute ago)
|
||||
Damn! We lost! (2 minutes ago)
|
||||
```
|
||||
|
||||
Following: Charlie can subscribe to Alice’s and Bob’s timelines, and view an aggregated list of all subscriptions
|
||||
|
||||
```
|
||||
> Charlie -> I'm in New York today! Anyone want to have a coffee?
|
||||
> Charlie follows Alice
|
||||
> Charlie wall
|
||||
Charlie - I'm in New York today! Anyone want to have a coffee? (2 seconds ago)
|
||||
Alice - I love the weather today (5 minutes ago)
|
||||
|
||||
> Charlie follows Bob
|
||||
> Charlie wall
|
||||
Charlie - I'm in New York today! Anyone wants to have a coffee? (15 seconds ago)
|
||||
Bob - Good game though. (1 minute ago)
|
||||
Bob - Damn! We lost! (2 minutes ago)
|
||||
Alice - I love the weather today (5 minutes ago)
|
||||
```
|
||||
|
||||
<h2>Details</h2>
|
||||
|
||||
* The application uses the console for input and output.
|
||||
* Users submit commands to the application.
|
||||
* There are four commands. “posting”, “reading”, etc. are not part of the commands.
|
||||
* Commands always start with the user’s name.
|
||||
* posting: user name -> message
|
||||
* reading: user name
|
||||
* following: user name follows another user
|
||||
* wall: user name wall
|
||||
|
||||
<h2>How to run the application</h2>
|
||||
|
||||
* Clone the repository.
|
||||
* Enter repository folder.
|
||||
* Run the app with:
|
||||
`.\gradlew run -q --console=plain` in Windows or
|
||||
`./gradlew run -q --console=plain` in Linux.
|
||||
* Alternatively you can also run from within the IDE:
|
||||
Load the class `com.lookiero.ConsoleTwitter` and run the `main()` function.
|
||||
* To stop the app, `press Ctrl + C`
|
||||
|
||||
<h2>Tests</h2>
|
||||
|
||||
A series of tests have been added with the following coverage:
|
||||
|
||||

|
||||
|
||||
To run the tests, execute `.\gradlew test` (`./gradlew test` in Linux)
|
||||
|
||||
Report is generated in `.\consoletwitter\build\reports\tests\test\index.html`
|
||||
21
build.gradle
Normal file
21
build.gradle
Normal file
@@ -0,0 +1,21 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id "application"
|
||||
}
|
||||
|
||||
group = 'com.droideparanoico'
|
||||
version = '0.0.1-SNAPSHOT'
|
||||
mainClassName = 'com.droideparanoico.consoletwitter.ConsoleTwitter'
|
||||
|
||||
run{
|
||||
standardInput = System.in
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
testImplementation 'org.mockito:mockito-core:3.6.28'
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.droideparanoico.consoletwitter;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
import com.droideparanoico.consoletwitter.command.CommandInterpreter;
|
||||
import com.droideparanoico.consoletwitter.repository.Repository;
|
||||
import com.droideparanoico.consoletwitter.ui.ConsoleTwitterPrinter;
|
||||
import com.droideparanoico.consoletwitter.ui.Printer;
|
||||
import com.droideparanoico.consoletwitter.repository.UserRepository;
|
||||
|
||||
/**
|
||||
* ConsoleTwitter - Main class.
|
||||
*/
|
||||
public class ConsoleTwitter {
|
||||
private static final String WELCOME = "Welcome to Console Twitter. Please, enter a command:\n";
|
||||
private static final String PROMPT = "> ";
|
||||
private static final Scanner scanner = new Scanner(System.in);
|
||||
|
||||
@SuppressWarnings("InfiniteLoopStatement")
|
||||
public static void main(String[] args) {
|
||||
Repository userRepository = new UserRepository();
|
||||
Printer printer = new ConsoleTwitterPrinter(System.out);
|
||||
CommandInterpreter commandInterpreter = new CommandInterpreter(userRepository, printer);
|
||||
System.out.print(WELCOME);
|
||||
|
||||
// Infinite loop to accept and display commands
|
||||
while (true) {
|
||||
System.out.print(PROMPT);
|
||||
String input = scanner.nextLine();
|
||||
commandInterpreter.executeCommand(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.droideparanoico.consoletwitter.command;
|
||||
|
||||
public interface Command {
|
||||
/**
|
||||
* Executes the input command string
|
||||
*
|
||||
* @param commandLine
|
||||
* Command string to execute
|
||||
*/
|
||||
void execute(String commandLine);
|
||||
|
||||
/**
|
||||
* Checks if the given command is able to execute the given string
|
||||
*
|
||||
* @param input
|
||||
* command string which is able to be executed with this command
|
||||
* @return boolean
|
||||
*/
|
||||
boolean matches(String input);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.droideparanoico.consoletwitter.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.droideparanoico.consoletwitter.repository.Repository;
|
||||
import com.droideparanoico.consoletwitter.ui.Printer;
|
||||
|
||||
public class CommandInterpreter {
|
||||
private final List<Command> commands = new ArrayList<>();
|
||||
private final Command invalidCommand;
|
||||
|
||||
public CommandInterpreter(Repository userRepository, Printer printer) {
|
||||
commands.add(new PostCommand(userRepository));
|
||||
commands.add(new ReadCommand(userRepository, printer));
|
||||
commands.add(new FollowCommand(userRepository));
|
||||
commands.add(new WallCommand(userRepository, printer));
|
||||
|
||||
invalidCommand = new InvalidCommand(printer);
|
||||
}
|
||||
|
||||
public void executeCommand(String commandLine) {
|
||||
Command command = getCommand(commandLine);
|
||||
command.execute(commandLine);
|
||||
}
|
||||
|
||||
public Command getCommand(String commandLine) {
|
||||
for (Command command : commands) {
|
||||
if (command.matches(commandLine))
|
||||
return command;
|
||||
}
|
||||
return invalidCommand;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.droideparanoico.consoletwitter.command;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.User;
|
||||
import com.droideparanoico.consoletwitter.repository.Repository;
|
||||
|
||||
public class FollowCommand implements Command {
|
||||
private static final Pattern REGEX = Pattern.compile("^(\\S+) follows (\\S+)$");
|
||||
private final Repository repository;
|
||||
|
||||
public FollowCommand(Repository userRepository) {
|
||||
this.repository = userRepository;
|
||||
}
|
||||
|
||||
public void execute(String commandLine) {
|
||||
Matcher matcher = REGEX.matcher(commandLine);
|
||||
matcher.find();
|
||||
String userName = matcher.group(1);
|
||||
String userNameToFollow = matcher.group(2);
|
||||
|
||||
User currentUser = repository.getOrCreateUser(userName);
|
||||
User userToFollow = repository.getOrCreateUser(userNameToFollow);
|
||||
currentUser.addFollowing(userToFollow);
|
||||
}
|
||||
|
||||
public boolean matches(String input) {
|
||||
if (input != null && !input.isEmpty()) {
|
||||
Matcher matcher = REGEX.matcher(input);
|
||||
return matcher.find();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.droideparanoico.consoletwitter.command;
|
||||
|
||||
import com.droideparanoico.consoletwitter.ui.Printer;
|
||||
|
||||
public class InvalidCommand implements Command {
|
||||
|
||||
private final Printer postDisplayer;
|
||||
|
||||
public InvalidCommand(Printer postDisplayer) {
|
||||
this.postDisplayer = postDisplayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String commandLine) {
|
||||
postDisplayer.printMessage(String.format("Command: %s is invalid!", commandLine));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(String input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.droideparanoico.consoletwitter.command;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.User;
|
||||
import com.droideparanoico.consoletwitter.repository.Repository;
|
||||
|
||||
public class PostCommand implements Command {
|
||||
private static final Pattern REGEX = Pattern.compile("^(\\S+) -> (.+)$");
|
||||
|
||||
private final Repository userRepository;
|
||||
|
||||
public PostCommand(Repository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
public void execute(String commandLine) {
|
||||
Matcher matcher = REGEX.matcher(commandLine);
|
||||
matcher.find();
|
||||
|
||||
String userName = matcher.group(1);
|
||||
String message = matcher.group(2);
|
||||
|
||||
User user = userRepository.getOrCreateUser(userName);
|
||||
user.addPost(message);
|
||||
}
|
||||
|
||||
public boolean matches(String input) {
|
||||
if (input != null && !input.isEmpty()) {
|
||||
Matcher matcher = REGEX.matcher(input);
|
||||
return matcher.find();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.droideparanoico.consoletwitter.command;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.Message;
|
||||
import com.droideparanoico.consoletwitter.domain.User;
|
||||
import com.droideparanoico.consoletwitter.repository.Repository;
|
||||
import com.droideparanoico.consoletwitter.ui.Printer;
|
||||
|
||||
public class ReadCommand implements Command {
|
||||
private static final Pattern REGEX = Pattern.compile("^\\S+$");
|
||||
|
||||
private final Repository userRepository;
|
||||
private final Printer postDisplayer;
|
||||
|
||||
public ReadCommand(Repository userRepository, Printer postDisplayer) {
|
||||
this.userRepository = userRepository;
|
||||
this.postDisplayer = postDisplayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String commandLine) {
|
||||
User user = userRepository.getOrCreateUser(commandLine.trim());
|
||||
List<Message> messages = user.getPosts();
|
||||
// Sort messages.
|
||||
messages.sort((p1, p2) -> p2.getPublishDate().compareTo(p1.getPublishDate()));
|
||||
for (Message message : messages) {
|
||||
postDisplayer.printPostForUser(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(String input) {
|
||||
if (input != null && !input.isEmpty()) {
|
||||
Matcher matcher = REGEX.matcher(input);
|
||||
return matcher.find();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.droideparanoico.consoletwitter.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.Message;
|
||||
import com.droideparanoico.consoletwitter.domain.User;
|
||||
import com.droideparanoico.consoletwitter.repository.Repository;
|
||||
import com.droideparanoico.consoletwitter.ui.Printer;
|
||||
|
||||
public class WallCommand implements Command {
|
||||
private static final Pattern REGEX = Pattern.compile("^(\\S+) wall$");
|
||||
|
||||
private final Repository userRepository;
|
||||
private final Printer postDisplayer;
|
||||
|
||||
public WallCommand(Repository userRepository, Printer postDisplayer) {
|
||||
this.userRepository = userRepository;
|
||||
this.postDisplayer = postDisplayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String commandLine) {
|
||||
Matcher matcher = REGEX.matcher(commandLine);
|
||||
matcher.find();
|
||||
|
||||
String userName = matcher.group(1);
|
||||
User user = userRepository.getOrCreateUser(userName);
|
||||
// Get user's messages.
|
||||
List<Message> messages = new ArrayList<>(user.getPosts());
|
||||
// Add following users post.
|
||||
for (User following : user.getFollowingUsers()) {
|
||||
messages.addAll(following.getPosts());
|
||||
}
|
||||
// Sort messages.
|
||||
messages.sort((p1, p2) -> p2.getPublishDate().compareTo(p1.getPublishDate()));
|
||||
for (Message message : messages) {
|
||||
postDisplayer.printPostForWall(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(String input) {
|
||||
if (input != null && !input.isEmpty()) {
|
||||
Matcher matcher = REGEX.matcher(input);
|
||||
return matcher.find();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.droideparanoico.consoletwitter.domain;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class Message {
|
||||
private String userName;
|
||||
private String message;
|
||||
private Date publishDate;
|
||||
|
||||
public Message(String userName, String message) {
|
||||
this.userName = userName;
|
||||
this.message = message;
|
||||
this.publishDate = new Date();
|
||||
}
|
||||
|
||||
public Message(String userName, String message, Date publishDate) {
|
||||
this.userName = userName;
|
||||
this.message = message;
|
||||
this.publishDate = publishDate;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public Date getPublishDate() {
|
||||
return publishDate;
|
||||
}
|
||||
|
||||
public void setPublishDate(Date publishDate) {
|
||||
this.publishDate = publishDate;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.droideparanoico.consoletwitter.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class User {
|
||||
private String name;
|
||||
private List<Message> messages = new ArrayList<>();
|
||||
private List<User> followingUsers = new ArrayList<>();
|
||||
|
||||
public User(String userName) {
|
||||
this.name = userName;
|
||||
}
|
||||
|
||||
public void addPost(String message) {
|
||||
messages.add(new Message(name, message));
|
||||
}
|
||||
|
||||
public void addFollowing(User user) {
|
||||
if (!followingUsers.contains(user)) {
|
||||
followingUsers.add(user);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Message> getPosts() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
public void setPosts(List<Message> messages) {
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
public List<User> getFollowingUsers() {
|
||||
return followingUsers;
|
||||
}
|
||||
|
||||
public void setFollowingUsers(List<User> followingUsers) {
|
||||
this.followingUsers = followingUsers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
User other = (User) obj;
|
||||
return name.equals(other.name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.droideparanoico.consoletwitter.repository;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.User;
|
||||
|
||||
public interface Repository {
|
||||
/**
|
||||
* Recovers the user from the repository, if the user does not exist, the method creates it.
|
||||
*
|
||||
* @param userName
|
||||
* The username.
|
||||
* @return The requested user.
|
||||
*
|
||||
*/
|
||||
User getOrCreateUser(String userName);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.droideparanoico.consoletwitter.repository;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.User;
|
||||
|
||||
public class UserRepository implements Repository {
|
||||
private final Map<String, User> userMap = new HashMap<>();
|
||||
|
||||
public User getOrCreateUser(String userName) {
|
||||
User user = userMap.get(userName);
|
||||
if (user == null) {
|
||||
user = new User(userName);
|
||||
userMap.put(userName, user);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.droideparanoico.consoletwitter.ui;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.Message;
|
||||
|
||||
public class ConsoleTwitterPrinter implements Printer {
|
||||
private static final String MESSAGE_FORMAT_FOR_WALL = "%s - %s %s";
|
||||
private static final String MESSAGE_FORMAT_FOR_USER = "%s %s";
|
||||
private final PrintStream printStream;
|
||||
|
||||
public ConsoleTwitterPrinter(PrintStream printStream) {
|
||||
this.printStream = printStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printPostForWall(Message message) {
|
||||
printStream.printf((MESSAGE_FORMAT_FOR_WALL) + "%n", message.getUserName(), message.getMessage(),
|
||||
getTimeAgo(message.getPublishDate().getTime()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printPostForUser(Message message) {
|
||||
printStream.printf((MESSAGE_FORMAT_FOR_USER) + "%n", message.getMessage(),
|
||||
getTimeAgo(message.getPublishDate().getTime()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printMessage(String message) {
|
||||
printStream.println(message);
|
||||
}
|
||||
|
||||
private static String getTimeAgo(long publishDate) {
|
||||
long now = System.currentTimeMillis();
|
||||
long diff = now - publishDate;
|
||||
long timeUnitDiff;
|
||||
String timeUnit;
|
||||
|
||||
if (diff < TimeUnit.MINUTES.toMillis(1)) {
|
||||
timeUnitDiff = TimeUnit.MILLISECONDS.toSeconds(diff);
|
||||
timeUnit = "second";
|
||||
} else if (diff < TimeUnit.HOURS.toMillis(1)) {
|
||||
timeUnitDiff = TimeUnit.MILLISECONDS.toMinutes(diff);
|
||||
timeUnit = "minute";
|
||||
} else if (diff < TimeUnit.DAYS.toMillis(1)) {
|
||||
timeUnitDiff = TimeUnit.MILLISECONDS.toHours(diff);
|
||||
timeUnit = "hour";
|
||||
} else {
|
||||
timeUnitDiff = TimeUnit.MILLISECONDS.toDays(diff);
|
||||
timeUnit = "day";
|
||||
}
|
||||
|
||||
if (timeUnitDiff > 1) {
|
||||
timeUnit = timeUnit + "s";
|
||||
}
|
||||
return String.format("(%d %s ago)", timeUnitDiff, timeUnit);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.droideparanoico.consoletwitter.ui;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.Message;
|
||||
|
||||
public interface Printer {
|
||||
|
||||
/**
|
||||
* Print the message as it will display on the wall.
|
||||
*
|
||||
* @param message
|
||||
* The message to be printed.
|
||||
*/
|
||||
void printPostForWall(Message message);
|
||||
|
||||
/**
|
||||
* print the message as it will display on the user timeline.
|
||||
*
|
||||
* @param message
|
||||
* The message to be printed.
|
||||
*/
|
||||
void printPostForUser(Message message);
|
||||
|
||||
/**
|
||||
* Print the message.
|
||||
*
|
||||
* @param message
|
||||
* The message to be printed.
|
||||
*/
|
||||
void printMessage(String message);
|
||||
|
||||
}
|
||||
BIN
src/main/resources/coverage.png
Normal file
BIN
src/main/resources/coverage.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.6 KiB |
@@ -0,0 +1,22 @@
|
||||
package com.droideparanoico.consoletwitter;
|
||||
|
||||
import com.droideparanoico.consoletwitter.command.*;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.MessageTest;
|
||||
import com.droideparanoico.consoletwitter.domain.UserTest;
|
||||
import com.droideparanoico.consoletwitter.repository.UserRepositoryTest;
|
||||
import com.droideparanoico.consoletwitter.ui.ConsoleTwitterPrinterTest;
|
||||
|
||||
/**
|
||||
* Unit tests for Console Twitter.
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({ CommandInterpreterTest.class, FollowCommandTest.class, MessageCommandTest.class, ReadCommandTest.class,
|
||||
WallCommandTest.class, MessageTest.class, UserTest.class, ConsoleTwitterPrinterTest.class,
|
||||
UserRepositoryTest.class, InvalidCommandTest.class })
|
||||
public class ConsoleTwitterTest {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.droideparanoico.consoletwitter.command;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import com.droideparanoico.consoletwitter.repository.Repository;
|
||||
import com.droideparanoico.consoletwitter.ui.ConsoleTwitterPrinter;
|
||||
import com.droideparanoico.consoletwitter.ui.Printer;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.User;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CommandInterpreterTest {
|
||||
private static final String USER = "David";
|
||||
private static final String USER_2 = "Julia";
|
||||
private static final String MESSAGE = "Happy new year!";
|
||||
private static final String POST_COMMAND = USER + " -> " + MESSAGE;
|
||||
private static final String FOLLOW_COMMAND = USER + " follows " + USER_2;
|
||||
private static final String WALL_COMMAND = USER + " wall";
|
||||
|
||||
private CommandInterpreter commandInterpreter;
|
||||
|
||||
@Mock
|
||||
private Repository userRepository;
|
||||
private PrintStream printStream;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
Printer printer = new ConsoleTwitterPrinter(printStream);
|
||||
commandInterpreter = spy(new CommandInterpreter(userRepository, printer));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executePostCommandTest() {
|
||||
User user = mock(User.class);
|
||||
when(userRepository.getOrCreateUser(USER)).thenReturn(user);
|
||||
commandInterpreter.executeCommand(POST_COMMAND);
|
||||
verify(commandInterpreter).getCommand(POST_COMMAND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPostCommandTest() {
|
||||
Command returnedCommand = commandInterpreter.getCommand(POST_COMMAND);
|
||||
Assert.assertTrue(returnedCommand instanceof PostCommand);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFollowCommandTest() {
|
||||
Command returnedCommand = commandInterpreter.getCommand(FOLLOW_COMMAND);
|
||||
Assert.assertTrue(returnedCommand instanceof FollowCommand);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReadCommandTest() {
|
||||
Command returnedCommand = commandInterpreter.getCommand(USER);
|
||||
Assert.assertTrue(returnedCommand instanceof ReadCommand);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWallCommandTest() {
|
||||
Command returnedCommand = commandInterpreter.getCommand(WALL_COMMAND);
|
||||
Assert.assertTrue(returnedCommand instanceof WallCommand);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.droideparanoico.consoletwitter.command;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.droideparanoico.consoletwitter.repository.Repository;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.User;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class FollowCommandTest {
|
||||
private static final String USER_1 = "David";
|
||||
private static final String USER_2 = "Julia";
|
||||
private static final String COMMAND = USER_1 + " follows " + USER_2;
|
||||
|
||||
private FollowCommand command;
|
||||
|
||||
@Mock
|
||||
private Repository userRepository;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
command = new FollowCommand(userRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatch() {
|
||||
Assert.assertTrue(command.matches(COMMAND));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchNull() {
|
||||
Assert.assertFalse(command.matches(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchEmptyl() {
|
||||
Assert.assertFalse(command.matches(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFollow() {
|
||||
User user1 = spy(new User(USER_1));
|
||||
User user2 = mock(User.class);
|
||||
|
||||
when(userRepository.getOrCreateUser(USER_1)).thenReturn(user1);
|
||||
when(userRepository.getOrCreateUser(USER_2)).thenReturn(user2);
|
||||
|
||||
command.execute(COMMAND);
|
||||
|
||||
verify(userRepository).getOrCreateUser(USER_1);
|
||||
verify(userRepository).getOrCreateUser(USER_2);
|
||||
verify(user1).addFollowing(user2);
|
||||
Assert.assertTrue(user1.getFollowingUsers().contains(user2));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.droideparanoico.consoletwitter.command;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.droideparanoico.consoletwitter.ui.ConsoleTwitterPrinter;
|
||||
import com.droideparanoico.consoletwitter.ui.Printer;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class InvalidCommandTest {
|
||||
private static final String USER = "David cucu";
|
||||
|
||||
private InvalidCommand command;
|
||||
private ByteArrayOutputStream baos;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
baos = new ByteArrayOutputStream();
|
||||
PrintStream printStream = new PrintStream(baos);
|
||||
Printer printer = new ConsoleTwitterPrinter(printStream);
|
||||
command = new InvalidCommand(printer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatch() {
|
||||
Assert.assertFalse(command.matches(USER));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchNull() {
|
||||
Assert.assertFalse(command.matches(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchEmptyl() {
|
||||
Assert.assertFalse(command.matches(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRead() {
|
||||
command.execute(USER);
|
||||
|
||||
String result = baos.toString(StandardCharsets.UTF_8);
|
||||
String expectedResult = String.format("Command: %s is invalid!\r\n", USER);
|
||||
Assert.assertEquals(expectedResult, result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.droideparanoico.consoletwitter.command;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.droideparanoico.consoletwitter.repository.Repository;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.User;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MessageCommandTest {
|
||||
private static final String USER = "David";
|
||||
private static final String MESSAGE = "Happy new year!";
|
||||
private static final String COMMAND = USER + " -> " + MESSAGE;
|
||||
|
||||
private PostCommand command;
|
||||
|
||||
@Mock
|
||||
private Repository userRepository;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
command = new PostCommand(userRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatch() {
|
||||
Assert.assertTrue(command.matches(COMMAND));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchNull() {
|
||||
Assert.assertFalse(command.matches(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchEmptyl() {
|
||||
Assert.assertFalse(command.matches(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPost() {
|
||||
User user = mock(User.class);
|
||||
|
||||
when(userRepository.getOrCreateUser(USER)).thenReturn(user);
|
||||
|
||||
command.execute(COMMAND);
|
||||
|
||||
verify(userRepository).getOrCreateUser(USER);
|
||||
verify(user).addPost(MESSAGE);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.droideparanoico.consoletwitter.command;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.Message;
|
||||
import com.droideparanoico.consoletwitter.repository.Repository;
|
||||
import com.droideparanoico.consoletwitter.ui.ConsoleTwitterPrinter;
|
||||
import com.droideparanoico.consoletwitter.ui.Printer;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.User;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ReadCommandTest {
|
||||
private static final String USER = "David";
|
||||
|
||||
private ReadCommand command;
|
||||
|
||||
@Mock
|
||||
private Repository userRepository;
|
||||
private ByteArrayOutputStream baos;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
baos = new ByteArrayOutputStream();
|
||||
PrintStream printStream = new PrintStream(baos);
|
||||
Printer printer = new ConsoleTwitterPrinter(printStream);
|
||||
command = new ReadCommand(userRepository, printer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatch() {
|
||||
Assert.assertTrue(command.matches(USER));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchNull() {
|
||||
Assert.assertFalse(command.matches(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchEmptyl() {
|
||||
Assert.assertFalse(command.matches(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRead() {
|
||||
User user = spy(new User(USER));
|
||||
user.setPosts(Arrays.asList(new Message(USER, "Happy new year!", new Date(
|
||||
System.currentTimeMillis() - 5 * 1000L)),
|
||||
new Message(USER, "Best wishes to everyone", new Date(System.currentTimeMillis() - 10 * 1000L))));
|
||||
|
||||
when(userRepository.getOrCreateUser(USER)).thenReturn(user);
|
||||
|
||||
command.execute(USER);
|
||||
|
||||
verify(userRepository).getOrCreateUser(USER);
|
||||
|
||||
String result = baos.toString(StandardCharsets.UTF_8);
|
||||
String expectedResult = "Happy new year! (5 seconds ago)\r\nBest wishes to everyone (10 seconds ago)\r\n";
|
||||
Assert.assertEquals(expectedResult, result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.droideparanoico.consoletwitter.command;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.Message;
|
||||
import com.droideparanoico.consoletwitter.repository.Repository;
|
||||
import com.droideparanoico.consoletwitter.ui.ConsoleTwitterPrinter;
|
||||
import com.droideparanoico.consoletwitter.ui.Printer;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.User;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class WallCommandTest {
|
||||
private static final String USER = "David";
|
||||
private static final String USER_2 = "Julia";
|
||||
private static final String COMMAND = USER + " wall";
|
||||
|
||||
private WallCommand command;
|
||||
@Mock
|
||||
private Repository userRepository;
|
||||
private ByteArrayOutputStream baos;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
baos = new ByteArrayOutputStream();
|
||||
PrintStream printStream = new PrintStream(baos);
|
||||
Printer printer = new ConsoleTwitterPrinter(printStream);
|
||||
command = new WallCommand(userRepository, printer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatch() {
|
||||
Assert.assertTrue(command.matches(COMMAND));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchNull() {
|
||||
Assert.assertFalse(command.matches(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchEmpty() {
|
||||
Assert.assertFalse(command.matches(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRead() {
|
||||
User user = spy(new User(USER));
|
||||
user.setPosts(Arrays.asList(new Message(USER, "Happy new year!", new Date(
|
||||
System.currentTimeMillis() - 5 * 1000L)),
|
||||
new Message(USER, "Best wishes to everyone", new Date(System.currentTimeMillis() - 20 * 1000L))));
|
||||
|
||||
User user2 = spy(new User(USER_2));
|
||||
user2.setPosts(Collections.singletonList(new Message(USER_2, "Time to get cozy", new Date(System.currentTimeMillis() - 10 * 1000L))));
|
||||
|
||||
user.addFollowing(user2);
|
||||
|
||||
when(userRepository.getOrCreateUser(USER)).thenReturn(user);
|
||||
|
||||
command.execute(COMMAND);
|
||||
|
||||
verify(userRepository).getOrCreateUser(USER);
|
||||
verify(user).getPosts();
|
||||
verify(user).getFollowingUsers();
|
||||
|
||||
verify(user2).getPosts();
|
||||
|
||||
String result = baos.toString(StandardCharsets.UTF_8);
|
||||
String expectedResult = "David - Happy new year! (5 seconds ago)\r\nJulia - Time to get cozy (10 seconds ago)\r\nDavid - Best wishes to everyone (20 seconds ago)\r\n";
|
||||
Assert.assertEquals(expectedResult, result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.droideparanoico.consoletwitter.domain;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MessageTest {
|
||||
|
||||
@Test
|
||||
public void testPost() {
|
||||
Message message = new Message("David", "Happy new year!");
|
||||
Assert.assertEquals("Happy new year!", message.getMessage());
|
||||
Assert.assertEquals("David", message.getUserName());
|
||||
Assert.assertNotNull(message.getPublishDate());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.droideparanoico.consoletwitter.domain;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class UserTest {
|
||||
private User user;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
user = new User("David");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPost() {
|
||||
user.addPost("Happy new year!");
|
||||
Assert.assertEquals(1, user.getPosts().size());
|
||||
Assert.assertEquals("Happy new year!", user.getPosts().get(0).getMessage());
|
||||
Assert.assertEquals("David", user.getPosts().get(0).getUserName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFollowing() {
|
||||
user.addFollowing(new User("Julia"));
|
||||
Assert.assertEquals(1, user.getFollowingUsers().size());
|
||||
Assert.assertEquals("Julia", user.getFollowingUsers().get(0).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUniqueFollowing() {
|
||||
user.addFollowing(new User("Julia"));
|
||||
user.addFollowing(new User("Julia"));
|
||||
Assert.assertEquals(1, user.getFollowingUsers().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetFollowing() {
|
||||
user.setFollowingUsers(Collections.singletonList(new User("Julia")));
|
||||
Assert.assertEquals(1, user.getFollowingUsers().size());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.droideparanoico.consoletwitter.repository;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.User;
|
||||
|
||||
public class UserRepositoryTest {
|
||||
private static final String USER = "David";
|
||||
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
userRepository = new UserRepository();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOrCreateUser() {
|
||||
User user = userRepository.getOrCreateUser(USER);
|
||||
Assert.assertNotNull(user);
|
||||
Assert.assertEquals(USER, user.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetExistingUser() {
|
||||
User user = userRepository.getOrCreateUser(USER);
|
||||
User existingUser = userRepository.getOrCreateUser(USER);
|
||||
Assert.assertEquals(user, existingUser);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.droideparanoico.consoletwitter.ui;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
|
||||
import com.droideparanoico.consoletwitter.domain.Message;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ConsoleTwitterPrinterTest {
|
||||
private ConsoleTwitterPrinter printer;
|
||||
private ByteArrayOutputStream baos;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
baos = new ByteArrayOutputStream();
|
||||
PrintStream printStream = new PrintStream(baos);
|
||||
printer = new ConsoleTwitterPrinter(printStream);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayPostForUserWithSeconds() {
|
||||
Message message = new Message("David", "Happy new year!", new Date(System.currentTimeMillis() - 10 * 1000L));
|
||||
printer.printPostForUser(message);
|
||||
String expectedResult = "Happy new year! (10 seconds ago)\r\n";
|
||||
Assert.assertEquals(expectedResult, baos.toString(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayPostForUserWithMinutes() {
|
||||
Message message = new Message("David", "Happy new year!", new Date(System.currentTimeMillis() - 10 * 60 * 1000L));
|
||||
printer.printPostForUser(message);
|
||||
String expectedResult = "Happy new year! (10 minutes ago)\r\n";
|
||||
Assert.assertEquals(expectedResult, baos.toString(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayPostForUserWithHours() {
|
||||
Message message = new Message("David", "Happy new year!", new Date(System.currentTimeMillis() - 2 * 60 * 60 * 1000L));
|
||||
printer.printPostForUser(message);
|
||||
String expectedResult = "Happy new year! (2 hours ago)\r\n";
|
||||
Assert.assertEquals(expectedResult, baos.toString(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayPostForUserWithDays() {
|
||||
Message message = new Message("David", "Happy new year!", new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000L));
|
||||
printer.printPostForUser(message);
|
||||
String expectedResult = "Happy new year! (1 day ago)\r\n";
|
||||
Assert.assertEquals(expectedResult, baos.toString(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayPostForWall() {
|
||||
Message message = new Message("David", "Happy new year!", new Date(System.currentTimeMillis() - 10 * 1000L));
|
||||
printer.printPostForWall(message);
|
||||
String expectedResult = "David - Happy new year! (10 seconds ago)\r\n";
|
||||
Assert.assertEquals(expectedResult, baos.toString(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayMessage() {
|
||||
String message = "Hello!";
|
||||
printer.printMessage(message);
|
||||
Assert.assertEquals(message + "\r\n", baos.toString(StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user