diff --git a/pom.xml b/pom.xml index dc2e28b62..14c16b82f 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ org.projectlombok lombok - 1.18.24 + 1.18.30 provided @@ -104,6 +104,11 @@ org.flywaydb flyway-core + + org.webjars + font-awesome + 4.7.0 + diff --git a/src/main/java/com/makersacademy/acebook/SecurityConfiguration.java b/src/main/java/com/makersacademy/acebook/SecurityConfiguration.java index a6829646e..c3df96c5a 100644 --- a/src/main/java/com/makersacademy/acebook/SecurityConfiguration.java +++ b/src/main/java/com/makersacademy/acebook/SecurityConfiguration.java @@ -28,11 +28,11 @@ protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/posts").hasRole("USER") .antMatchers("/users").permitAll() - .and().formLogin(); + .and().formLogin().loginPage("/login"); } @Bean public PasswordEncoder getPasswordEncoder() { return NoOpPasswordEncoder.getInstance(); } -} +} \ No newline at end of file diff --git a/src/main/java/com/makersacademy/acebook/controller/CommentController.java b/src/main/java/com/makersacademy/acebook/controller/CommentController.java new file mode 100644 index 000000000..5b031d41a --- /dev/null +++ b/src/main/java/com/makersacademy/acebook/controller/CommentController.java @@ -0,0 +1,89 @@ +package com.makersacademy.acebook.controller; + +import com.makersacademy.acebook.model.Comment; +import com.makersacademy.acebook.model.Post; +import com.makersacademy.acebook.model.User; +import com.makersacademy.acebook.repository.CommentRepository; +import com.makersacademy.acebook.repository.PostRepository; +import com.makersacademy.acebook.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import java.security.Principal; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Optional; + +@Controller +public class CommentController { + + + @Autowired + PostRepository postRepository; + + @Autowired + CommentRepository commentRepository; + + @Autowired + UserRepository userRepository; + + @GetMapping("/post/{id}") + public String show(@PathVariable Long id, Model model, Principal principal) { + +// get post to display at the top of page + Optional post = postRepository.findById(id); + Post currentPost = post.orElse(null); + model.addAttribute("currentPost", currentPost); + + + Optional postUser = userRepository.findById(currentPost.getUserId()); + User postOwner = postUser.orElse(null); + model.addAttribute("postOwner", postOwner); + + Optional currentUser = userRepository.findByUsername(principal.getName()); + User principalUser = currentUser.orElse(null); + + +// create new comment object to make a new comment using the form + Comment commentObj = new Comment(); + model.addAttribute("newComment", commentObj); + +// Create a LinkedHashMap to store sorted data + LinkedHashMap commentsAndOwners = new LinkedHashMap<>(); + +// get an ordered list of comments associated with the post we are visiting + List comments = commentRepository.findAllByPostIdOrderById(id); + model.addAttribute("comments", comments); + +// for each comment, find the associated user/owner and add both to LinkedHaspMap + for (Comment comment : comments) { + Optional commentOwner = userRepository.findById(comment.getUserId()); + User user = commentOwner.orElse(null); + commentsAndOwners.put(comment, user); + } +// System.out.println(commentsAndOwners); + model.addAttribute("commentsAndOwners", commentsAndOwners); + model.addAttribute("currentUser", principalUser); + model.addAttribute("profilePicture", principalUser.getImageUrl()); + + return "posts/show"; + } + + @PostMapping("/post/addComment") + public String createComment(@RequestParam String comment, @RequestParam Long postId, Principal principal) { + +// Get userID + Optional currentUser = userRepository.findByUsername(principal.getName()); + User principalUser = currentUser.orElse(null); + + Comment newComment = new Comment(comment, postId, principalUser.getId()); + + commentRepository.save(newComment); + + return "redirect:/post/" + postId; + + } +} diff --git a/src/main/java/com/makersacademy/acebook/controller/FriendController.java b/src/main/java/com/makersacademy/acebook/controller/FriendController.java new file mode 100644 index 000000000..c235f987e --- /dev/null +++ b/src/main/java/com/makersacademy/acebook/controller/FriendController.java @@ -0,0 +1,98 @@ +package com.makersacademy.acebook.controller; + +import com.makersacademy.acebook.model.Friend; +import com.makersacademy.acebook.model.User; +import com.makersacademy.acebook.repository.FriendRepository; +import com.makersacademy.acebook.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.view.RedirectView; + +import java.security.Principal; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +@Controller +public class FriendController { + + @Autowired + FriendRepository friendRepository; + @Autowired + UserRepository userRepository; + + @GetMapping("/users/friend") + public ModelAndView showFriends(Model model) { + ModelAndView modelAndView = new ModelAndView("/users/friend"); + modelAndView.addObject("friend", new Friend()); + return modelAndView; + } + + @GetMapping("/friends") + public ModelAndView showRequests(Principal principal) { + ModelAndView modelAndView = new ModelAndView("/users/friends"); + + Optional currentUser = userRepository.findByUsername(principal.getName()); + User principalUser = currentUser.orElse(null); + + assert principalUser != null; + List pendingRequests = friendRepository.findByStatusAndReceiverId(principalUser.getId(), "PENDING"); + List acceptedRequests = friendRepository.findByStatusAndReceiverId(principalUser.getId(), "ACCEPTED"); + + ArrayList friendRequests = new ArrayList<>(); + for (Friend friend : pendingRequests) { + Optional optionalUser = userRepository.findById(friend.getRequesterId()); + User friendRequest = optionalUser.orElse(null); + friendRequests.add(friendRequest); + } + + ArrayList friends = new ArrayList<>(); + for (Friend friend : acceptedRequests) { + Optional optionalUser = userRepository.findById(friend.getRequesterId()); + User acceptedRequest = optionalUser.orElse(null); + friends.add(acceptedRequest); + } + + modelAndView.addObject("friendRequests", friendRequests); + modelAndView.addObject("friends", friends); + modelAndView.addObject("currentUser", principalUser); + modelAndView.addObject("profilePicture", principalUser.getImageUrl()); + return modelAndView; + } + + @PostMapping("/handleFriendRequest") + public RedirectView handleFriendRequest(@RequestParam("requester_id") Long requesterId, + @RequestParam("receiver_id") Long receiverId, Principal principal) { + + Optional currentUser = userRepository.findByUsername(principal.getName()); + User principalUser = currentUser.orElse(null); + assert principalUser != null; + + Friend friendRequest = new Friend(requesterId, receiverId, "PENDING"); + friendRepository.save(friendRequest); + + return new RedirectView("/users/" + receiverId); + } + + @PostMapping("/handleFriendConfirmation") + public String handleConfirmation(@RequestParam("action") String action, + @RequestParam("requesterId") Long requesterId, Principal principal) { + Optional currentUser = userRepository.findByUsername(principal.getName()); + User receiverId = currentUser.orElse(null); + assert receiverId != null; + + if ("accept".equals(action)) { + friendRepository.updateStatusByRequesterIdAndReceiverId(requesterId, receiverId.getId(), "ACCEPTED"); + } else if ("deny".equals(action)) { + friendRepository.updateStatusByRequesterIdAndReceiverId(requesterId, receiverId.getId(), "DENIED"); + } + + return "redirect:/friends"; + } +} diff --git a/src/main/java/com/makersacademy/acebook/controller/HomeController.java b/src/main/java/com/makersacademy/acebook/controller/HomeController.java index 2036ec7e0..40b353725 100644 --- a/src/main/java/com/makersacademy/acebook/controller/HomeController.java +++ b/src/main/java/com/makersacademy/acebook/controller/HomeController.java @@ -4,10 +4,24 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.view.RedirectView; +import javax.servlet.http.HttpSession; + @Controller public class HomeController { @RequestMapping(value = "/") public RedirectView index() { return new RedirectView("/posts"); } + + @RequestMapping("/login") + public String login() { + return "login"; + } + @RequestMapping("/logout") + public String logout(HttpSession session) { + session.removeAttribute("user_id"); + return "logout"; + } + } + diff --git a/src/main/java/com/makersacademy/acebook/controller/PostsController.java b/src/main/java/com/makersacademy/acebook/controller/PostsController.java index 57a7e5f4d..ea26368ae 100644 --- a/src/main/java/com/makersacademy/acebook/controller/PostsController.java +++ b/src/main/java/com/makersacademy/acebook/controller/PostsController.java @@ -1,32 +1,77 @@ package com.makersacademy.acebook.controller; +import com.makersacademy.acebook.model.Comment; +import com.makersacademy.acebook.model.Friend; import com.makersacademy.acebook.model.Post; +import com.makersacademy.acebook.model.User; +import com.makersacademy.acebook.repository.CommentRepository; import com.makersacademy.acebook.repository.PostRepository; +import com.makersacademy.acebook.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.view.RedirectView; -import java.util.List; +import java.security.Principal; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.*; @Controller public class PostsController { @Autowired - PostRepository repository; + PostRepository postRepository; + @Autowired + UserRepository userRepository; @GetMapping("/posts") - public String index(Model model) { - Iterable posts = repository.findAll(); - model.addAttribute("posts", posts); - model.addAttribute("post", new Post()); + public String index(Model model, Principal principal) { + Optional currentUser = userRepository.findByUsername(principal.getName()); + User principalUser = currentUser.orElse(null); + assert principalUser != null; + + Iterable posts = postRepository.findAllByOrderByTimestampDesc(); + ArrayList> postsAndPosters = new ArrayList<>(); + + for (Post post : posts) { + HashMap entry = new HashMap<>(); + + Optional optionalUser = userRepository.findById(post.getUserId()); + User poster = optionalUser.orElse(null); + + entry.put(post, poster); + postsAndPosters.add(entry); + } + +// System.out.println(postsAndPosters); + + model.addAttribute("postsAndPosters", postsAndPosters); + model.addAttribute("newPost", new Post()); + model.addAttribute("profilePicture", principalUser.getImageUrl()); + model.addAttribute("currentUser", principalUser); + return "posts/index"; } @PostMapping("/posts") - public RedirectView create(@ModelAttribute Post post) { - repository.save(post); + public RedirectView create(@ModelAttribute Post post, Principal principal) { + +// get and set timestamp of post + String timeStamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date()); + post.setTimestamp(Timestamp.valueOf(timeStamp)); + +// get user and set userid of post + Optional currentUser = userRepository.findByUsername(principal.getName()); + User principalUser = currentUser.orElse(null); + post.setUserId(principalUser.getId()); + +// save post + postRepository.save(post); + return new RedirectView("/posts"); } + } diff --git a/src/main/java/com/makersacademy/acebook/controller/UsersController.java b/src/main/java/com/makersacademy/acebook/controller/UsersController.java index 3c46bf0a1..e02d56835 100644 --- a/src/main/java/com/makersacademy/acebook/controller/UsersController.java +++ b/src/main/java/com/makersacademy/acebook/controller/UsersController.java @@ -1,17 +1,27 @@ package com.makersacademy.acebook.controller; import com.makersacademy.acebook.model.Authority; +import com.makersacademy.acebook.model.Friend; +import com.makersacademy.acebook.model.Post; import com.makersacademy.acebook.model.User; import com.makersacademy.acebook.repository.AuthoritiesRepository; +import com.makersacademy.acebook.repository.FriendRepository; import com.makersacademy.acebook.repository.UserRepository; +import com.makersacademy.acebook.repository.PostRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.servlet.view.RedirectView; +import javax.servlet.http.HttpSession; +import java.security.Principal; +import java.util.*; + +import static java.lang.Boolean.valueOf; + @Controller public class UsersController { @@ -19,6 +29,10 @@ public class UsersController { UserRepository userRepository; @Autowired AuthoritiesRepository authoritiesRepository; + @Autowired + FriendRepository friendRepository; + @Autowired + PostRepository postRepository; @GetMapping("/users/new") public String signup(Model model) { @@ -27,10 +41,66 @@ public String signup(Model model) { } @PostMapping("/users") - public RedirectView signup(@ModelAttribute User user) { + public RedirectView signup(@ModelAttribute User user, @RequestParam("fileData") String fileData) { + user.setImageUrl(fileData); + userRepository.save(user); Authority authority = new Authority(user.getUsername(), "ROLE_USER"); authoritiesRepository.save(authority); return new RedirectView("/login"); } + + @GetMapping("/users/{id}") + public ModelAndView show(@PathVariable Long id, Principal principal, Model model) { + Optional pageUser = userRepository.findById(id); + User user = pageUser.orElse(null); + + Optional currentUser = userRepository.findByUsername(principal.getName()); + User principalUser = currentUser.orElse(null); + assert principalUser != null; + + ModelAndView modelAndView = new ModelAndView("/users/show"); + modelAndView.addObject("currentUser", principalUser); + modelAndView.addObject("user", user); + + Iterable userRequests = friendRepository.findByRequesterIdOrReceiverId(principalUser.getId(), principalUser.getId()); + + for (Friend friend : userRequests) { + if (Objects.equals(friend.getReceiverId(), id) || Objects.equals(friend.getRequesterId(), id)) { + modelAndView.addObject("userRequest", friend); + break; + } else { + modelAndView.addObject("userRequest", null); + } + } + + if (principal.getName().equals(Objects.requireNonNull(user).getUsername())) { + modelAndView.addObject("isCurrentUser", true); + } else { + modelAndView.addObject("isCurrentUser", false); + } + + Iterable posts = postRepository.findAllByOrderByTimestampDesc(); + ArrayList> postsAndPosters = new ArrayList<>(); + + for (Post post : posts) { + HashMap entry = new HashMap<>(); + + Optional optionalUser = userRepository.findById(post.getUserId()); + User poster = optionalUser.orElse(null); + + if (post.getUserId() == id) { + entry.put(post, poster); + postsAndPosters.add(entry); + } + + } + + + model.addAttribute("profilePicture", principalUser.getImageUrl()); + model.addAttribute("postsAndPosters", postsAndPosters); + + return modelAndView; + } + } diff --git a/src/main/java/com/makersacademy/acebook/model/Authority.java b/src/main/java/com/makersacademy/acebook/model/Authority.java index 775b3bde2..2fb5d820e 100644 --- a/src/main/java/com/makersacademy/acebook/model/Authority.java +++ b/src/main/java/com/makersacademy/acebook/model/Authority.java @@ -1,7 +1,6 @@ package com.makersacademy.acebook.model; import lombok.Data; - import javax.persistence.*; @Data diff --git a/src/main/java/com/makersacademy/acebook/model/Comment.java b/src/main/java/com/makersacademy/acebook/model/Comment.java new file mode 100644 index 000000000..a5f6d262d --- /dev/null +++ b/src/main/java/com/makersacademy/acebook/model/Comment.java @@ -0,0 +1,49 @@ +package com.makersacademy.acebook.model; + + +import lombok.Data; +import lombok.Getter; + +import javax.persistence.*; + + +@Data +@Entity +@Table(name = "COMMENTS") +public class Comment { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Getter + private String comment; + @Getter + private Long postId; + @Getter + private Long userId; + +// @ManyToOne(cascade = CascadeType.ALL) +// @JoinColumn(name = "post_id") +// private Post post; + + public Comment() {}; + + public Comment(String comment, Long postId, Long userId) { + this.comment = comment; + this.postId = postId; + this.userId = userId; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public void setPostId(Long postId) { + this.postId = postId; + } + + public void setUserId(Long UserId) { + this.userId = UserId; + } +} diff --git a/src/main/java/com/makersacademy/acebook/model/Friend.java b/src/main/java/com/makersacademy/acebook/model/Friend.java new file mode 100644 index 000000000..a78bb3c5e --- /dev/null +++ b/src/main/java/com/makersacademy/acebook/model/Friend.java @@ -0,0 +1,40 @@ +package com.makersacademy.acebook.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.GenerationType; + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +@Data +@Entity +@Table(name = "FRIENDS") +public class Friend { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @Getter + private Long requesterId; + @Getter + private Long receiverId; + @Getter + private String status; + + public Friend() {} + + public Friend(Long requester_id, Long receiver_id, String status) { + this.requesterId = requester_id; + this.receiverId = receiver_id; + this.status = status; + } + + public void setRequesterId(Long requester_id) { this.requesterId = requester_id; } + public void setReceiverId(Long receiver_id) { this.receiverId = receiver_id; } + public void setStatus(String status) { this.status = status; } + +} diff --git a/src/main/java/com/makersacademy/acebook/model/Post.java b/src/main/java/com/makersacademy/acebook/model/Post.java index 0098de1b3..a5974e25c 100644 --- a/src/main/java/com/makersacademy/acebook/model/Post.java +++ b/src/main/java/com/makersacademy/acebook/model/Post.java @@ -1,12 +1,11 @@ package com.makersacademy.acebook.model; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Table; -import javax.persistence.GenerationType; +import javax.persistence.*; import lombok.Data; +import lombok.Getter; + +import java.sql.Timestamp; @Data @Entity @@ -16,14 +15,30 @@ public class Post { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Getter private String content; + @Getter + private Timestamp timestamp; + + @Getter + private Long userId; + +// @Getter +// @OneToMany(fetch = FetchType.LAZY, mappedBy = "post", cascade = CascadeType.ALL) +// private List commentList; + public Post() {} - public Post(String content) { + public Post(String content, Timestamp timestamp, Long userId) { this.content = content; + this.timestamp = timestamp; + this.userId = userId; } - public String getContent() { return this.content; } public void setContent(String content) { this.content = content; } + public void setTimestamp(Timestamp timestamp) { this.timestamp = timestamp; } + + public void setUserId(Long userId) { this.userId = userId; } } diff --git a/src/main/java/com/makersacademy/acebook/model/User.java b/src/main/java/com/makersacademy/acebook/model/User.java index df2a0edf1..84a10a83d 100644 --- a/src/main/java/com/makersacademy/acebook/model/User.java +++ b/src/main/java/com/makersacademy/acebook/model/User.java @@ -7,6 +7,7 @@ import javax.persistence.GenerationType; import lombok.Data; +import lombok.Getter; import static java.lang.Boolean.TRUE; @@ -14,31 +15,37 @@ @Entity @Table(name = "USERS") public class User { + @Getter @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Getter private String username; + @Getter private String password; private boolean enabled; + @Getter String imageUrl; + public User() { this.enabled = TRUE; } - public User(String username, String password) { + public User(String username, String password, String imageUrl) { this.username = username; this.password = password; + this.imageUrl = imageUrl; this.enabled = TRUE; } - public User(String username, String password, boolean enabled) { + public User(String username, String password, String imageUrl, boolean enabled) { this.username = username; this.password = password; + this.imageUrl = imageUrl; this.enabled = enabled; } - public String getUsername() { return this.username; } - public String getPassword() { return this.password; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } + public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; } } diff --git a/src/main/java/com/makersacademy/acebook/repository/CommentRepository.java b/src/main/java/com/makersacademy/acebook/repository/CommentRepository.java new file mode 100644 index 000000000..da839326e --- /dev/null +++ b/src/main/java/com/makersacademy/acebook/repository/CommentRepository.java @@ -0,0 +1,10 @@ +package com.makersacademy.acebook.repository; + +import com.makersacademy.acebook.model.Comment; +import org.springframework.data.repository.CrudRepository; + +import java.util.List; + +public interface CommentRepository extends CrudRepository { + public List findAllByPostIdOrderById(Long postId); +} diff --git a/src/main/java/com/makersacademy/acebook/repository/FriendRepository.java b/src/main/java/com/makersacademy/acebook/repository/FriendRepository.java new file mode 100644 index 000000000..7e646658d --- /dev/null +++ b/src/main/java/com/makersacademy/acebook/repository/FriendRepository.java @@ -0,0 +1,26 @@ +package com.makersacademy.acebook.repository; + +import com.makersacademy.acebook.model.Friend; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Optional; + +public interface FriendRepository extends CrudRepository { + @Query("SELECT f FROM Friend f WHERE f.receiverId = :receiverId AND f.status = :status") + List findByStatusAndReceiverId(@Param("receiverId") Long receiverId, @Param("status") String status); + + @Query("SELECT f FROM Friend f WHERE f.requesterId = :requesterId OR f.receiverId = :receiverId") + List findByRequesterIdOrReceiverId(@Param("requesterId") Long requesterId, @Param("receiverId") Long receiverId); + + @Transactional + @Modifying + @Query("UPDATE Friend f SET f.status = :status WHERE f.requesterId = :requesterId AND f.receiverId = :receiverId") + void updateStatusByRequesterIdAndReceiverId(@Param("requesterId") Long requesterId, + @Param("receiverId") Long receiverId, @Param("status") String status); + +} diff --git a/src/main/java/com/makersacademy/acebook/repository/PostRepository.java b/src/main/java/com/makersacademy/acebook/repository/PostRepository.java index d435e0ce1..de89f3772 100644 --- a/src/main/java/com/makersacademy/acebook/repository/PostRepository.java +++ b/src/main/java/com/makersacademy/acebook/repository/PostRepository.java @@ -4,6 +4,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.repository.CrudRepository; -public interface PostRepository extends CrudRepository { +import java.util.List; +public interface PostRepository extends CrudRepository { + public List findAllByOrderByTimestampDesc(); } diff --git a/src/main/java/com/makersacademy/acebook/repository/UserRepository.java b/src/main/java/com/makersacademy/acebook/repository/UserRepository.java index 2cccc950f..5f1f0eaa2 100644 --- a/src/main/java/com/makersacademy/acebook/repository/UserRepository.java +++ b/src/main/java/com/makersacademy/acebook/repository/UserRepository.java @@ -3,6 +3,8 @@ import com.makersacademy.acebook.model.User; import org.springframework.data.repository.CrudRepository; -public interface UserRepository extends CrudRepository { +import java.util.Optional; +public interface UserRepository extends CrudRepository { + Optional findByUsername(String username); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index c7ad09d6d..2d031b6d8 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -3,3 +3,5 @@ spring.data.rest.base-path=/api spring.datasource.platform=postgres spring.jpa.hibernate.ddl-auto=validate logging.level.org.springframework.web: DEBUG +jsf.primefaces.FONT_AWESOME=true + diff --git a/src/main/resources/db/migration/V10__update_userid_to_bigint.sql b/src/main/resources/db/migration/V10__update_userid_to_bigint.sql new file mode 100644 index 000000000..83c91ad42 --- /dev/null +++ b/src/main/resources/db/migration/V10__update_userid_to_bigint.sql @@ -0,0 +1,3 @@ +ALTER TABLE posts +ALTER COLUMN user_id +TYPE bigint; diff --git a/src/main/resources/db/migration/V11__update_userid_and_postid_to_bigint.sql b/src/main/resources/db/migration/V11__update_userid_and_postid_to_bigint.sql new file mode 100644 index 000000000..ccf94621b --- /dev/null +++ b/src/main/resources/db/migration/V11__update_userid_and_postid_to_bigint.sql @@ -0,0 +1,8 @@ +ALTER TABLE comments +ALTER COLUMN post_id TYPE bigint; + +ALTER TABLE comments +ALTER COLUMN user_id TYPE bigint; + + + diff --git a/src/main/resources/db/migration/V12__alter_friends_table.sql b/src/main/resources/db/migration/V12__alter_friends_table.sql new file mode 100644 index 000000000..b5e6e91b5 --- /dev/null +++ b/src/main/resources/db/migration/V12__alter_friends_table.sql @@ -0,0 +1,5 @@ +ALTER TABLE FRIENDS +ALTER COLUMN requester_id TYPE BIGINT; + +ALTER TABLE FRIENDS +ALTER COLUMN receiver_id TYPE BIGINT; diff --git a/src/main/resources/db/migration/V13__update_posts_with_timestamps.sql b/src/main/resources/db/migration/V13__update_posts_with_timestamps.sql new file mode 100644 index 000000000..93ea0610b --- /dev/null +++ b/src/main/resources/db/migration/V13__update_posts_with_timestamps.sql @@ -0,0 +1,44 @@ +update + posts +set + timestamp = '2023-11-14 11:13:24', + user_id = 3 +where + content = 'Second post'; + + +update + posts +set + timestamp = '2023-11-15 11:13:24', + user_id = 10 +where + content = 'fourth post'; + + +update + posts +set + timestamp = '2023-11-16 11:13:24', + user_id = 11 +where + content = 'third post'; + + +update + posts +set + timestamp = '2023-11-10 11:13:24', + user_id = 12 +where + content = 'sixth post'; + + +update + posts +set + timestamp = '2023-11-09 11:13:24', + user_id = 14 +where + content = 'fifth post'; + diff --git a/src/main/resources/db/migration/V15__add_user_1_for_testing.sql b/src/main/resources/db/migration/V15__add_user_1_for_testing.sql new file mode 100644 index 000000000..d4a312101 --- /dev/null +++ b/src/main/resources/db/migration/V15__add_user_1_for_testing.sql @@ -0,0 +1,3 @@ +INSERT INTO users +(username, password, enabled, image_url) +VALUES ('test_user', 'password22', true, null); \ No newline at end of file diff --git a/src/main/resources/db/migration/V16__insert_test_users_into_authorities_table.sql b/src/main/resources/db/migration/V16__insert_test_users_into_authorities_table.sql new file mode 100644 index 000000000..a2e5d1477 --- /dev/null +++ b/src/main/resources/db/migration/V16__insert_test_users_into_authorities_table.sql @@ -0,0 +1,6 @@ +insert into + authorities (username, authority) +values + ('zak', 'ROLE_USER'), + ('david', 'ROLE_USER'), + ('som', 'ROLE_USER'); \ No newline at end of file diff --git a/src/main/resources/db/migration/V17__add_test_user_to_authorities_table.sql b/src/main/resources/db/migration/V17__add_test_user_to_authorities_table.sql new file mode 100644 index 000000000..f82b1ff3f --- /dev/null +++ b/src/main/resources/db/migration/V17__add_test_user_to_authorities_table.sql @@ -0,0 +1,4 @@ +insert into + authorities (username, authority) +values + ('test_user', 'ROLE_USER'); \ No newline at end of file diff --git a/src/main/resources/db/migration/V18__update_imageUrl_column_to_text.sql b/src/main/resources/db/migration/V18__update_imageUrl_column_to_text.sql new file mode 100644 index 000000000..b0eb4c232 --- /dev/null +++ b/src/main/resources/db/migration/V18__update_imageUrl_column_to_text.sql @@ -0,0 +1,2 @@ +ALTER TABLE USERS +ALTER COLUMN image_url TYPE TEXT; \ No newline at end of file diff --git a/src/main/resources/db/migration/V3__update_existing_create_new_tables.sql b/src/main/resources/db/migration/V3__update_existing_create_new_tables.sql new file mode 100644 index 000000000..6032cbbfc --- /dev/null +++ b/src/main/resources/db/migration/V3__update_existing_create_new_tables.sql @@ -0,0 +1,38 @@ +ALTER TABLE posts +ADD COLUMN timestamp timestamp, +ADD COLUMN user_id integer, +ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users(id); + + +ALTER TABLE users +ADD image_url varchar(500); + + +CREATE TABLE likes ( + id bigserial PRIMARY KEY, + like_status boolean DEFAULT false, + user_id integer, + post_id integer, + FOREIGN KEY (user_id) REFERENCES users(id), + FOREIGN KEY (post_id) REFERENCES posts(id), + UNIQUE (user_id, post_id) +); + + +CREATE TABLE comments ( + id bigserial PRIMARY KEY, + comment varchar(281) NOT NULL, + post_id integer, + user_id integer, + FOREIGN KEY (post_id) REFERENCES posts(id), + FOREIGN KEY (user_id) REFERENCES users(id) +); + +CREATE TABLE friends ( + id bigserial PRIMARY KEY, + requester_id integer, + receiver_id integer, + FOREIGN KEY (requester_id) REFERENCES users(id), + FOREIGN KEY (receiver_id) REFERENCES users(id), + status varchar(50) check (status in ('ACCEPTED', 'PENDING', 'DENIED')) +); \ No newline at end of file diff --git a/src/main/resources/db/migration/V4__insert_test_data.sql b/src/main/resources/db/migration/V4__insert_test_data.sql new file mode 100644 index 000000000..26c1fd78d --- /dev/null +++ b/src/main/resources/db/migration/V4__insert_test_data.sql @@ -0,0 +1,7 @@ +insert into users (username, password, enabled, image_url) +values ('zak', '12345', TRUE, '/users/images/image.png'), + ('david', '123456', TRUE, '/users/images/another_image.png'); + + + + diff --git a/src/main/resources/db/migration/V5__insert_into_posts.sql b/src/main/resources/db/migration/V5__insert_into_posts.sql new file mode 100644 index 000000000..5df524f2a --- /dev/null +++ b/src/main/resources/db/migration/V5__insert_into_posts.sql @@ -0,0 +1,2 @@ +insert into posts (content, timestamp, user_id) +values ('first post', '2023-11-14 11:13:24', 2); \ No newline at end of file diff --git a/src/main/resources/db/migration/V9__add_new_user.sql b/src/main/resources/db/migration/V9__add_new_user.sql new file mode 100644 index 000000000..1b26a72e1 --- /dev/null +++ b/src/main/resources/db/migration/V9__add_new_user.sql @@ -0,0 +1,2 @@ +insert into users (username, password, enabled, image_url) +values ('som', '123457', TRUE, '/users/images/image_three.png'); diff --git a/src/main/resources/static/website.css b/src/main/resources/static/website.css new file mode 100644 index 000000000..a7cce8cc0 --- /dev/null +++ b/src/main/resources/static/website.css @@ -0,0 +1,379 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,300;1,400;1,500;1,600;1,700;1,800&display=swap'); + +html { + font-family: 'Poppins', sans-serif; +} + +body { + background-color: #f3f3ec; + color: black; /* Text color for body */ + margin: 0; + padding: 0; +} + +.header { + background-color: #ADD8E6; /* Header background color */ + color: black; /* Text color for header */ + padding-left: 35px; + display: flex; + justify-content: space-between; + align-content: stretch; + height: 75px; +} + +.header-title { + display: flex; + margin: 15px 0px; + height: 45px; +} + +.header-title-name { + margin-right: 5px; +} + +.profile-image { + color: black; + text-decoration: none; + font-size: 1.8rem; + border-radius: 50%; /* Make the profile image round */ + object-fit: cover; + margin-right: 10px; +} + +.profile-image img { + border-radius: 50%; /* Make the profile image round */ + object-fit: cover; + margin-right: 10px; +} + +.header-title-name { + margin-left: 10px; + text-transform: capitalize; +} + +.menu-right { + display: flex; + align-items: center; +} + +.menu-right a { + color: black; /* Text color for menu links */ + margin: 0 10px; + text-decoration: none; + transform: scale(1.08); +} + +.menu-right a:hover { + transform: scale(1.08); + color: white; +} + +.menu-right form { + margin: 0; +} + +.menu-right input[type="submit"] { + background-color: #ADD8E6; + color: black; + padding: 0px 10px; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 16px; + transform: scale(1.08); +} + +.menu-right input[type="submit"]:hover { + background-color: #ADD8E6; +} + +.contentForm, .commentForm{ + max-width: 80%; + margin: 3.5rem; + padding: 20px; + background-color: #f3f3ec; +} + +.userSignup, .userLogin { + max-width: 50%; + margin: 0 auto; + padding: 20px; + background-color: #fafaf7; + border-radius: 5px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); +} + + +textarea{ + background-color: #f3f3ec; +} + +.listed { + max-width: 30%; + margin: 0rem; + padding: 20px; + background-color: #fafaf7; + border-radius: 5px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); +} + + +.postContainer { + list-style: none; +} + +input[type="text"], +input[type="password"], +input[type="file"] { + width: 100%; + padding: 10px; + margin-bottom: 10px; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 4px; + color: black; /* Text color for input fields */ +} + +input[type="submit"], +input[type="reset"] { + background-color: #ADD8E6; + color: black; + padding: 10px 15px; + margin-right: 5px; + border: none; + border-radius: 4px; + cursor: pointer; + transition: transform 0.3s; +} + +input[type="submit"]:hover, +input[type="reset"]:hover { + background-color: #177b90; + transform: scale(1.08); + color: white; +} + +button { + background-color: #ADD8E6; + color: black; + padding: 10px 15px; + border: none; + border-radius: 4px; + cursor: pointer; + transition: transform 0.3s; +} + +button:hover { + background-color: #177b90; + transform: scale(1.08); + color: white; +} + +.friendButton { + background-color: #ADD8E6; + color: black; + padding: 10px 15px; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.user-profile-container { + display: inline-flex; + margin: auto 30px; +} + +.user-profile-heading { + display: flex; + flex-direction: column; + margin: 35px 0px; +} + +.user-profile-title { + display: flex; + justify-content: center; + max-width: 180px; + text-transform: capitalize; + font-weight: 600; + font-size: 20px; +} + +.user-profile-image { + color: black; + text-decoration: none; + font-size: 1.8rem; + border-radius: 50%; /* Make the profile image round */ + object-fit: cover; + border: 2px solid black; +} + +.user-profile-request-btn { + display: flex; + justify-content: center; + max-width: 180px; +} + +.user-profile-post { + list-style: none; +} + +.user-card-posts { + max-width: 100%; + margin: 0rem; + padding: 20px; + background-color: #fafaf7; + border-radius: 5px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + list-style: none; +} + +.user-profile-timeline { + width: 700px; + margin-top: 20px; + list-style: none; + padding-inline-start: 0px; +} + +.user-profile-timeline ul { + padding-inline-start: 20px; +} + +.user-posts-header { + padding-left: 45px; +} + +.profile-with-name { + display: flex; + align-items: center; + text-decoration: none; + color: black; + transition: transform 0.3s; + text-transform: capitalize; + font-weight: 600; +} + +.profile-with-name:hover { + color: #177b90; +} + +.profile-with-name img { + border-radius: 50%; /* Make the profile image round */ + object-fit: cover; + margin-right: 10px; +} + +.comment-like-btns { + display: flex; + flex-direction: row; + justify-content: end; + height: 50px; +} + +.posts-timeline { + display: flex; + flex-direction: column; + justify-content: center; + width: 700px; + margin: 0px auto; + list-style: none; + padding-inline-start: 0px; +} + +.welcome-title { + display: flex; + justify-content: center; + margin: 15px 0px; + height: 45px; + padding-left: 40px; + font-size: 30px; +} + +.posts-content-form { + max-width: 100%; + background-color: #f3f3ec; + padding-left: 40px; +} + +.posts-content-form #timeline-form-content { + width: 93%; + padding: 20px; +} + +.timeline-posts { + padding-left: 0px; +} + +.posts-form-btns { + display: flex; + flex-direction: row; + justify-content: end; + margin-right: 5px; +} + +.post-content { + margin-bottom: 20px; +} + +input[type="submit-posts"] { + background-color: #ADD8E6; + color: black; + padding: 10px 15px; + border: none; + border-radius: 4px; + cursor: pointer; + transition: transform 0.3s; +} + +input[type="submit-posts"]:hover { + background-color: #177b90; + transform: scale(1.08); + color: white; +} + +.requests { + list-style: none; + width: 200px; + margin: 10px; + display: inline-grid; + align-items: center; + justify-items: center; +} + +.request-profile-with-name { + text-decoration: none; + color: black; + transition: transform 0.3s; + text-transform: capitalize; + font-weight: 600; +} + +.request-profile-with-name:hover { + color: #177b90; +} + +.request-profile-with-name img { + border-radius: 50%; /* Make the profile image round */ + object-fit: cover; + margin-right: 10px; +} + +.request-user-profile-title { + display: flex; + justify-content: center; + max-width: 180px; + text-transform: capitalize; + font-weight: 600; + font-size: 20px; + text-decoration: none; + transition: transform 0.3s; +} + +.user-profile-with-name:hover { + color: #177b90; +} + +.friends-with-requests { + display: flex; + flex-direction: row; + margin: 0 auto; +} \ No newline at end of file diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html new file mode 100644 index 000000000..91a597a9f --- /dev/null +++ b/src/main/resources/templates/login.html @@ -0,0 +1,33 @@ + + + + Please log in + + +
+
+
+ Please Login +
+ Invalid username and password. +
+
+ You have been logged out. +
+ + + + +
+ +
+
+
+
+
+ +
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/posts/index.html b/src/main/resources/templates/posts/index.html index 4eb260155..f39ff5913 100644 --- a/src/main/resources/templates/posts/index.html +++ b/src/main/resources/templates/posts/index.html @@ -1,27 +1,80 @@ - - - - Acebook - - - - -

Posts

- -
- Signed in as + + + + Acebook + + + + +
+ +
+ Acebook +
+
+
-
-

Content:

-

-
+
+
+ Welcome! +
+ +
+ + +

+
+ +
    +
      +
    • + + + +
      +

      +
      + +
      +
      +

      + + +

      +
      +
      + +
    • +
    +
+
-
    -
  • -
- + diff --git a/src/main/resources/templates/posts/show.html b/src/main/resources/templates/posts/show.html new file mode 100644 index 000000000..4a0f5d711 --- /dev/null +++ b/src/main/resources/templates/posts/show.html @@ -0,0 +1,67 @@ + + + + + + + + Acebook + + + +
+ +
+ Acebook +
+
+ +
+
+ + +

+ + +
+ + +

+
+ + + +
    +
  • + + + + + +

    +
  • +
+ + + \ No newline at end of file diff --git a/src/main/resources/templates/users/friends.html b/src/main/resources/templates/users/friends.html new file mode 100644 index 000000000..9f6315a98 --- /dev/null +++ b/src/main/resources/templates/users/friends.html @@ -0,0 +1,69 @@ + + + + + + Friends + + +
+ +
+ Acebook +
+
+ +
+ +
Friends
+
+
+ +
+
+
    +
  • + + + + + +
    + + + +
    +
  • +
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/templates/users/new.html b/src/main/resources/templates/users/new.html index 2d763f396..a25bea50c 100644 --- a/src/main/resources/templates/users/new.html +++ b/src/main/resources/templates/users/new.html @@ -1,14 +1,33 @@ - - + + + Signup + + -
-

Username:

-

Password:

+ +

Username:

+

Password:

+

Profile Picture:

+

diff --git a/src/main/resources/templates/users/show.html b/src/main/resources/templates/users/show.html new file mode 100644 index 000000000..538075256 --- /dev/null +++ b/src/main/resources/templates/users/show.html @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + +
+ +
+ Acebook +
+
+ +
+ + + + + \ No newline at end of file diff --git a/src/test/java/SignUpTest.java b/src/test/java/SignUpTest.java index b0e16955b..fec9926fa 100644 --- a/src/test/java/SignUpTest.java +++ b/src/test/java/SignUpTest.java @@ -7,7 +7,10 @@ import org.junit.runner.RunWith; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -38,6 +41,41 @@ public void successfulSignUpRedirectsToSignIn() { driver.findElement(By.id("password")).sendKeys("password"); driver.findElement(By.id("submit")).click(); String title = driver.getTitle(); - Assert.assertEquals("Please sign in", title); + Assert.assertEquals("Please log in", title); + } + + + @Test + public void signUpButtonLinksToSignUpPage() { + driver.get("http://localhost:8080/login"); + driver.findElement(By.id("sign-up-btn")).click(); + String title = driver.getTitle(); + Assert.assertEquals("Signup", title); + } + + @Test + public void testBlankUsernameReturnsError() { + driver.get("http://localhost:8080/users/new"); + driver.findElement(By.id("username")).sendKeys(" "); + driver.findElement(By.id("password")).sendKeys("password"); + driver.findElement(By.id("submit")).click(); + // Explicitly wait for the error message to be visible + WebDriverWait wait = new WebDriverWait(driver, 10); + WebElement usernameError = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("usernameError"))); + String errorString = usernameError.getText(); + Assert.assertEquals("Please enter a username", errorString); + } + + @Test + public void testBlankPasswordReturnsError() { + driver.get("http://localhost:8080/users/new"); + driver.findElement(By.id("username")).sendKeys("username_1"); + driver.findElement(By.id("password")).sendKeys(" "); + driver.findElement(By.id("submit")).click(); + // Explicitly wait for the error message to be visible + WebDriverWait wait = new WebDriverWait(driver, 10); + WebElement passwordError = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("passwordError"))); + String errorString = passwordError.getText(); + Assert.assertEquals("Please enter a password", errorString); } } diff --git a/src/test/java/com/makersacademy/acebook/model/PostTest.java b/src/test/java/com/makersacademy/acebook/model/PostTest.java index 732aafc6e..be918f1d3 100644 --- a/src/test/java/com/makersacademy/acebook/model/PostTest.java +++ b/src/test/java/com/makersacademy/acebook/model/PostTest.java @@ -5,13 +5,22 @@ import org.junit.Test; +import java.sql.Timestamp; + public class PostTest { - private Post post = new Post("hello"); + Timestamp timestamp = Timestamp.valueOf("2007-09-23 10:10:10.0");; + + private Post post = new Post("hello", timestamp, 1L); @Test public void postHasContent() { assertThat(post.getContent(), containsString("hello")); } + @Test + public void postHasU() { + assertThat(post.getContent(), containsString("hello")); + } + } diff --git a/src/test/java/com/makersacademy/aceboook/controller/CommentControllerTest.java b/src/test/java/com/makersacademy/aceboook/controller/CommentControllerTest.java new file mode 100644 index 000000000..ed8ecc610 --- /dev/null +++ b/src/test/java/com/makersacademy/aceboook/controller/CommentControllerTest.java @@ -0,0 +1,65 @@ +package com.makersacademy.aceboook.controller; + +import com.github.javafaker.Faker; +import com.makersacademy.acebook.Application; +import com.makersacademy.acebook.repository.CommentRepository; +import com.makersacademy.acebook.repository.PostRepository; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.List; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = Application.class) +public class CommentControllerTest { + + + @Autowired + PostRepository postRepository; + + @Autowired + CommentRepository commentRepository; + + WebDriver driver; + Faker faker; + + @Before + public void setup() { + System.setProperty("webdriver.chrome.driver", "/usr/local/bin/chromedriver"); + driver = new ChromeDriver(); + faker = new Faker(); + } + + @After + public void tearDown() { + driver.close(); + } + + @Test + public void testAddCommentReflectedInCommentsList() { + driver.get("http://localhost:8080/login"); + driver.findElement(By.id("username")).sendKeys("test_user"); + driver.findElement(By.id("password")).sendKeys("password22"); + driver.findElement(By.id("submit")).click(); + driver.findElement(By.id("comment")).click(); + driver.findElement(By.id("addComment")).sendKeys("Here is my new comment!"); + driver.findElement(By.id("submitComment")).click(); + + List commentsList = driver.findElements(By.id("commentContent")); + String comment = commentsList.get(commentsList.size() -1).getText(); + + Assert.assertEquals("Here is my new comment!", comment); + } + + +} diff --git a/src/test/java/com/makersacademy/aceboook/controller/PostControllerTest.java b/src/test/java/com/makersacademy/aceboook/controller/PostControllerTest.java new file mode 100644 index 000000000..aa512eebf --- /dev/null +++ b/src/test/java/com/makersacademy/aceboook/controller/PostControllerTest.java @@ -0,0 +1,98 @@ +package com.makersacademy.aceboook.controller; + +import com.github.javafaker.Faker; +import com.makersacademy.acebook.Application; +import com.makersacademy.acebook.model.Post; +import com.makersacademy.acebook.repository.PostRepository; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.List; + + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = Application.class) +public class PostControllerTest { + + + @Autowired + PostRepository postRepository; + + WebDriver driver; + Faker faker; + + @Before + public void setup() { + System.setProperty("webdriver.chrome.driver", "/usr/local/bin/chromedriver"); + driver = new ChromeDriver(); + faker = new Faker(); + } + + @After + public void tearDown() { + driver.close(); + } + + @Test + public void testNewPostIsAtTheTopOfList() { + driver.get("http://localhost:8080/login"); + driver.findElement(By.id("username")).sendKeys("test_user"); + driver.findElement(By.id("password")).sendKeys("password22"); + driver.findElement(By.id("submit")).click(); + driver.findElement(By.id("content")).sendKeys("New Post"); + driver.findElement(By.id("submit")).click(); + + WebElement ul = driver.findElement(By.tagName("ul")); + List postList = ul.findElements(By.id("postContent")); + + String newPost = postList.get(0).getText(); + + Assert.assertEquals("New Post", newPost); + } + + @Test + public void testNewPostHasUserIdAssigned() { + driver.get("http://localhost:8080/login"); + driver.findElement(By.id("username")).sendKeys("test_user"); + driver.findElement(By.id("password")).sendKeys("password22"); + driver.findElement(By.id("submit")).click(); + WebDriverWait wait = new WebDriverWait(driver, 10); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("content"))); + driver.findElement(By.id("content")).sendKeys("New Post"); + driver.findElement(By.id("submit")).click(); + List posts = postRepository.findAllByOrderByTimestampDesc(); + Post latestPost = posts.get(0); + Long userId = latestPost.getUserId(); + Long expected = 4L; + Assert.assertEquals(expected, userId); + } + + @Test + public void testCommentButtonNavigatesToPostPageFromPosts() { + driver.get("http://localhost:8080/login"); + driver.findElement(By.id("username")).sendKeys("test_user"); + driver.findElement(By.id("password")).sendKeys("password22"); + driver.findElement(By.id("submit")).click(); + driver.findElement(By.id("content")).sendKeys("Testing Comment Button"); + driver.findElement(By.id("submit")).click(); + driver.findElement(By.id("comment")).click(); + WebElement h3Element = driver.findElement(By.tagName("h3")); + String h3Text = h3Element.getText(); + Assert.assertEquals("Testing Comment Button", h3Text); + + } + + +} diff --git a/src/test/java/com/makersacademy/aceboook/controller/UsersControllerTest.java b/src/test/java/com/makersacademy/aceboook/controller/UsersControllerTest.java new file mode 100644 index 000000000..0f8b6cd87 --- /dev/null +++ b/src/test/java/com/makersacademy/aceboook/controller/UsersControllerTest.java @@ -0,0 +1,55 @@ +package com.makersacademy.aceboook.controller; + +import com.github.javafaker.Faker; +import com.makersacademy.acebook.Application; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = Application.class) +public class UsersControllerTest { + + WebDriver driver; + WebDriver page; + Faker faker; + + @Before + public void setup() { + System.setProperty("webdriver.chrome.driver", "/usr/local/bin/chromedriver"); + driver = new ChromeDriver(); + faker = new Faker(); + } + + @After + public void tearDown() { + driver.close(); + } + + @Test + public void usersCanReadUsername() { + driver.get("localhost:8080/users/3"); + WebElement pElement = driver.findElement(By.tagName("p")); + String pText = pElement.getText(); + Assert.assertEquals("zak ", pText); + + } + +// @Test +// public void successfulSignUpRedirectsToSignIn() { +// driver.get("http://localhost:8080/users/new"); +// driver.findElement(By.id("username")).sendKeys(faker.name().firstName()); +// driver.findElement(By.id("password")).sendKeys("password"); +// driver.findElement(By.id("submit")).click(); +// String title = driver.getTitle(); +// Assert.assertEquals("Please sign in", title); +// } +}