diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..3dbc8dd --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,34 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle + +name: Java CI with Gradle + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'temurin' + - name: Build with Gradle + uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 + with: + arguments: build diff --git a/build.gradle b/build.gradle index e3e5de5..6e46bab 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,8 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'mysql:mysql-connector-java' developmentOnly 'org.springframework.boot:spring-boot-devtools' testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' diff --git a/queries.sql b/queries.sql index 972c068..fa74c31 100644 --- a/queries.sql +++ b/queries.sql @@ -1,7 +1,20 @@ -- Part 1: Test it with SQL - +/* SHOW COLUMNS FROM job +Field: id TYPE: int +Field: employer TYPE: VARCHAR +Field: name TYPE: VARCHAR +Field: skills TYPE: VARCHAR */ -- Part 2: Test it with SQL +SELECT NAME +FROM employer +WHERE location = "St. Louis City"; -- Part 3: Test it with SQL --- Part 4: Test it with SQL \ No newline at end of file + DROP TABLE Job; + +-- Part 4: Test it with SQL +SELECT * FROM skill +LEFT JOIN job_skills ON skill.id = job_skills.skills_id +WHERE job_skills.jobs_id IS NOT NULL +ORDER BY name ASC; \ No newline at end of file diff --git a/src/main/java/org/launchcode/techjobs/persistent/controllers/EmployerController.java b/src/main/java/org/launchcode/techjobs/persistent/controllers/EmployerController.java index b297996..47065e7 100644 --- a/src/main/java/org/launchcode/techjobs/persistent/controllers/EmployerController.java +++ b/src/main/java/org/launchcode/techjobs/persistent/controllers/EmployerController.java @@ -1,6 +1,8 @@ package org.launchcode.techjobs.persistent.controllers; import org.launchcode.techjobs.persistent.models.Employer; +import org.launchcode.techjobs.persistent.models.data.EmployerRepository; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.Errors; @@ -13,6 +15,16 @@ @RequestMapping("employers") public class EmployerController { + @Autowired + private EmployerRepository employerRepository; + + //displays a list of all employers in db// + @GetMapping("") + public String index(Model model){ + model.addAttribute("employers", employerRepository.findAll()); + return "employers/index"; + } + @GetMapping("add") public String displayAddEmployerForm(Model model) { @@ -25,16 +37,17 @@ public String processAddEmployerForm(@ModelAttribute @Valid Employer newEmployer Errors errors, Model model) { if (errors.hasErrors()) { + model.addAttribute(new Employer()); return "employers/add"; } - + employerRepository.save(newEmployer); return "redirect:"; } @GetMapping("view/{employerId}") public String displayViewEmployer(Model model, @PathVariable int employerId) { - Optional optEmployer = null; + Optional optEmployer = employerRepository.findById(employerId); if (optEmployer.isPresent()) { Employer employer = (Employer) optEmployer.get(); model.addAttribute("employer", employer); diff --git a/src/main/java/org/launchcode/techjobs/persistent/controllers/HomeController.java b/src/main/java/org/launchcode/techjobs/persistent/controllers/HomeController.java index a3e5593..a024896 100644 --- a/src/main/java/org/launchcode/techjobs/persistent/controllers/HomeController.java +++ b/src/main/java/org/launchcode/techjobs/persistent/controllers/HomeController.java @@ -1,6 +1,14 @@ package org.launchcode.techjobs.persistent.controllers; + +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import org.launchcode.techjobs.persistent.models.Employer; import org.launchcode.techjobs.persistent.models.Job; +import org.launchcode.techjobs.persistent.models.Skill; +import org.launchcode.techjobs.persistent.models.data.EmployerRepository; +import org.launchcode.techjobs.persistent.models.data.JobRepository; +import org.launchcode.techjobs.persistent.models.data.SkillRepository; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.Errors; @@ -8,6 +16,9 @@ import javax.validation.Valid; import java.util.List; +import java.util.Optional; + +import static java.util.Optional.empty; /** * Created by LaunchCode @@ -15,10 +26,19 @@ @Controller public class HomeController { + @Autowired + private EmployerRepository employerRepository; + @Autowired + private JobRepository jobRepository; + @Autowired + private SkillRepository skillRepository; + + @RequestMapping("") public String index(Model model) { model.addAttribute("title", "My Jobs"); +// model.addAttribute("jobs", jobRepository.findAll()); return "index"; } @@ -26,26 +46,50 @@ public String index(Model model) { @GetMapping("add") public String displayAddJobForm(Model model) { model.addAttribute("title", "Add Job"); + model.addAttribute("employers", employerRepository.findAll()); + model.addAttribute("skills", skillRepository.findAll()); model.addAttribute(new Job()); return "add"; } @PostMapping("add") public String processAddJobForm(@ModelAttribute @Valid Job newJob, - Errors errors, Model model, @RequestParam int employerId, @RequestParam List skills) { + Errors errors, Model model, @RequestParam int employerId, @RequestParam List skills) { if (errors.hasErrors()) { model.addAttribute("title", "Add Job"); + model.addAttribute("employers", employerRepository.findAll()); + model.addAttribute("skills", skillRepository.findAll()); + model.addAttribute(new Job()); return "add"; } +// model.addAttribute("skills", skillRepository.findAllById(skills)); + +// Optional result = employerRepository.findById(employerId); +// +// Employer employer = (Employer) result.get(); +// model.addAttribute("employer", employer); +// } + Employer chosenEmployer = employerRepository.findById(employerId).orElse(new Employer("No Location")); + newJob.setEmployer(chosenEmployer); + + List skillObjs = (List) skillRepository.findAllById(skills); + newJob.setSkills(skillObjs); + jobRepository.save(newJob); return "redirect:"; } @GetMapping("view/{jobId}") public String displayViewJob(Model model, @PathVariable int jobId) { - - return "view"; + Optional optJob = jobRepository.findById(jobId); + if (optJob.isPresent()) { + Job job = (Job) optJob.get(); + model.addAttribute("job", job); + return "view"; + } else { + return "redirect:../"; + } } diff --git a/src/main/java/org/launchcode/techjobs/persistent/controllers/ListController.java b/src/main/java/org/launchcode/techjobs/persistent/controllers/ListController.java index 6e6bea9..5365bd6 100644 --- a/src/main/java/org/launchcode/techjobs/persistent/controllers/ListController.java +++ b/src/main/java/org/launchcode/techjobs/persistent/controllers/ListController.java @@ -1,8 +1,11 @@ package org.launchcode.techjobs.persistent.controllers; import org.launchcode.techjobs.persistent.models.Job; +import org.launchcode.techjobs.persistent.models.Skill; +import org.launchcode.techjobs.persistent.models.data.EmployerRepository; import org.launchcode.techjobs.persistent.models.data.JobRepository; import org.launchcode.techjobs.persistent.models.JobData; +import org.launchcode.techjobs.persistent.models.data.SkillRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -16,10 +19,14 @@ */ @Controller @RequestMapping(value = "list") -public class ListController { +public class ListController { @Autowired private JobRepository jobRepository; + @Autowired + private EmployerRepository employerRepository; + @Autowired + private SkillRepository skillRepository; static HashMap columnChoices = new HashMap<>(); @@ -33,6 +40,9 @@ public ListController () { @RequestMapping("") public String list(Model model) { + model.addAttribute("employers", employerRepository.findAll()); + model.addAttribute("skills", skillRepository.findAll()); +// model.addAttribute("jobs", jobRepository.findAll()); return "list"; } diff --git a/src/main/java/org/launchcode/techjobs/persistent/controllers/SkillController.java b/src/main/java/org/launchcode/techjobs/persistent/controllers/SkillController.java new file mode 100644 index 0000000..84fda67 --- /dev/null +++ b/src/main/java/org/launchcode/techjobs/persistent/controllers/SkillController.java @@ -0,0 +1,58 @@ +package org.launchcode.techjobs.persistent.controllers; + +import org.launchcode.techjobs.persistent.models.Employer; +import org.launchcode.techjobs.persistent.models.Skill; +import org.launchcode.techjobs.persistent.models.data.SkillRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.Errors; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.Optional; + +@Controller +@RequestMapping("skills") +public class SkillController { + @Autowired + private SkillRepository skillRepository; + + @GetMapping("") + public String index(Model model){ + model.addAttribute("skills", skillRepository.findAll()); + return "skills/index"; + } + + + @GetMapping("add") + public String displayAddSkillForm(Model model) { + model.addAttribute(new Skill()); + return "skills/add"; + } + + @PostMapping("add") + public String processAddSkillForm(@ModelAttribute @Valid Skill newSkill, + Errors errors, Model model) { + + if (errors.hasErrors()) { + return "skills/add"; + } + skillRepository.save(newSkill); + return "redirect:"; + } + + @GetMapping("view/{skillId}") + public String displayViewSkill(Model model, @PathVariable int skillId) { + + Optional optSkill = skillRepository.findById(skillId); + if (optSkill.isPresent()) { + Skill skill = (Skill) optSkill.get(); + model.addAttribute("skill", skill); + return "skills/view"; + } else { + return "redirect:../"; + } + } +} + diff --git a/src/main/java/org/launchcode/techjobs/persistent/models/AbstractEntity.java b/src/main/java/org/launchcode/techjobs/persistent/models/AbstractEntity.java index 1ad0722..b6bd050 100644 --- a/src/main/java/org/launchcode/techjobs/persistent/models/AbstractEntity.java +++ b/src/main/java/org/launchcode/techjobs/persistent/models/AbstractEntity.java @@ -1,14 +1,30 @@ package org.launchcode.techjobs.persistent.models; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; import java.util.Objects; - +@MappedSuperclass public abstract class AbstractEntity { + + @Id + @GeneratedValue private int id; + @NotBlank(message = "This is a required field. Must not be blank.") + @Size(min = 3, max = 120, message = "Name must be between 3 and 120 characters.") private String name; + + + public void setId(int id) { + this.id = id; + } + public int getId() { return id; } diff --git a/src/main/java/org/launchcode/techjobs/persistent/models/Employer.java b/src/main/java/org/launchcode/techjobs/persistent/models/Employer.java index 857397a..4eadd14 100644 --- a/src/main/java/org/launchcode/techjobs/persistent/models/Employer.java +++ b/src/main/java/org/launchcode/techjobs/persistent/models/Employer.java @@ -1,6 +1,40 @@ package org.launchcode.techjobs.persistent.models; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import java.util.ArrayList; +import java.util.List; + +@Entity public class Employer extends AbstractEntity { + @NotBlank(message = "This is a required field. Must not be blank.") + @Size(min = 3, max = 120, message = "Name must be between 3 and 120 characters.") + private String location; + + @OneToMany + @JoinColumn(name = "employer_id") + private final List jobs = new ArrayList<>(); + + public Employer(String location) { + this.location = location; + } + + public Employer() { + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + public List getJobs() { + return jobs; + } } diff --git a/src/main/java/org/launchcode/techjobs/persistent/models/Job.java b/src/main/java/org/launchcode/techjobs/persistent/models/Job.java index 56d215c..eaf0e77 100644 --- a/src/main/java/org/launchcode/techjobs/persistent/models/Job.java +++ b/src/main/java/org/launchcode/techjobs/persistent/models/Job.java @@ -1,51 +1,53 @@ package org.launchcode.techjobs.persistent.models; -import javax.persistence.*; +import javax.persistence.Entity; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; -@Entity -public class Job{ +import javax.validation.constraints.NotNull; +import java.util.ArrayList; - @Id - @GeneratedValue - private int id; +import java.util.List; +import java.util.ListIterator; - private String name; +@Entity +public class Job extends AbstractEntity{ - private String employer; - private String skills; + @ManyToOne + private Employer employer; - public Job() { - } + @ManyToMany + private List skills = new ArrayList<>(); - public Job(String anEmployer, String someSkills) { - super(); + public Job(Employer anEmployer, List someSkills) { this.employer = anEmployer; this.skills = someSkills; } - // Getters and setters. +// public Job(Employer anEmployer, String someSkills) { +// super(); +// this.employer = anEmployer; +// this.skills = someSkills; +// } - public String getName() { - return name; + public Job() { } - public void setName(String name) { - this.name = name; - } + // Getters and setters. - public String getEmployer() { + public Employer getEmployer() { return employer; } - public void setEmployer(String employer) { + public void setEmployer(Employer employer) { this.employer = employer; } - public String getSkills() { + public List getSkills() { return skills; } - public void setSkills(String skills) { + public void setSkills(List skills) { this.skills = skills; } } diff --git a/src/main/java/org/launchcode/techjobs/persistent/models/Skill.java b/src/main/java/org/launchcode/techjobs/persistent/models/Skill.java index acf49e8..67860fd 100644 --- a/src/main/java/org/launchcode/techjobs/persistent/models/Skill.java +++ b/src/main/java/org/launchcode/techjobs/persistent/models/Skill.java @@ -1,5 +1,40 @@ package org.launchcode.techjobs.persistent.models; +import javax.persistence.Entity; +import javax.persistence.ManyToMany; +import javax.validation.constraints.Size; +import java.util.ArrayList; +import java.util.List; + +@Entity public class Skill extends AbstractEntity { + @Size(max = 250, message = "Please keep description to 250 characters.") + private String description; + + @ManyToMany(mappedBy = "skills") + private List jobs = new ArrayList<>(); + + public Skill(String description) { + this.description = description; + } + + public Skill() { + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public List getJobs() { + return jobs; + } + public void setJobs(List jobs) { + this.jobs = jobs; + } + } \ No newline at end of file diff --git a/src/main/java/org/launchcode/techjobs/persistent/models/data/EmployerRepository.java b/src/main/java/org/launchcode/techjobs/persistent/models/data/EmployerRepository.java new file mode 100644 index 0000000..726829e --- /dev/null +++ b/src/main/java/org/launchcode/techjobs/persistent/models/data/EmployerRepository.java @@ -0,0 +1,9 @@ +package org.launchcode.techjobs.persistent.models.data; + +import org.launchcode.techjobs.persistent.models.Employer; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface EmployerRepository extends CrudRepository { +} diff --git a/src/main/java/org/launchcode/techjobs/persistent/models/data/SkillRepository.java b/src/main/java/org/launchcode/techjobs/persistent/models/data/SkillRepository.java new file mode 100644 index 0000000..58dfe4f --- /dev/null +++ b/src/main/java/org/launchcode/techjobs/persistent/models/data/SkillRepository.java @@ -0,0 +1,9 @@ +package org.launchcode.techjobs.persistent.models.data; + +import org.launchcode.techjobs.persistent.models.Skill; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface SkillRepository extends CrudRepository { +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8b13789..f1f4680 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,18 @@ +# Database connection settings +spring.datasource.url=jdbc:mysql://localhost:3306/techjobs +spring.datasource.username=techjobs +spring.datasource.password=techjobs +# Specify the DBMS +spring.jpa.database = MYSQL + +# Show or not log for each sql query +spring.jpa.show-sql = true + + +# Hibernate ddl auto (create, create-drop, update) +spring.jpa.hibernate.ddl-auto = update + +# Use spring.jpa.properties.* for Hibernate native properties (the prefix is +# stripped before adding them to the entity manager) +spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL8Dialect diff --git a/src/test/java/org/launchcode/techjobs/persistent/TestTaskFour.java b/src/test/java/org/launchcode/techjobs/persistent/TestTaskFour.java index a08eb6f..b5f60f8 100644 --- a/src/test/java/org/launchcode/techjobs/persistent/TestTaskFour.java +++ b/src/test/java/org/launchcode/techjobs/persistent/TestTaskFour.java @@ -9,7 +9,9 @@ import org.launchcode.techjobs.persistent.models.Employer; import org.launchcode.techjobs.persistent.models.Job; import org.launchcode.techjobs.persistent.models.Skill; +import org.launchcode.techjobs.persistent.models.data.EmployerRepository; import org.launchcode.techjobs.persistent.models.data.JobRepository; +import org.launchcode.techjobs.persistent.models.data.SkillRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.Model; @@ -109,110 +111,110 @@ public void testJobSkillsRefactoring () throws ClassNotFoundException, NoSuchMet /* * Verifies that HomeController has an @Autowired skillRepository field * */ -// @Test -// public void testHomeControllerHasSkillRepository () throws ClassNotFoundException { -// Class homeControllerClass = getClassByName("controllers.HomeController"); -// Field skillRepositoryField = null; -// try { -// skillRepositoryField = homeControllerClass.getDeclaredField("skillRepository"); -// } catch (NoSuchFieldException e) { -// fail("HomeController should have a skillRepository field"); -// } -// -// assertEquals(SkillRepository.class, skillRepositoryField.getType(), "skillRepository is of incorrect type"); -// assertNotNull(skillRepositoryField.getAnnotation(Autowired.class), "skillRepository must be @Autowired"); -// } + @Test + public void testHomeControllerHasSkillRepository () throws ClassNotFoundException { + Class homeControllerClass = getClassByName("controllers.HomeController"); + Field skillRepositoryField = null; + try { + skillRepositoryField = homeControllerClass.getDeclaredField("skillRepository"); + } catch (NoSuchFieldException e) { + fail("HomeController should have a skillRepository field"); + } + + assertEquals(SkillRepository.class, skillRepositoryField.getType(), "skillRepository is of incorrect type"); + assertNotNull(skillRepositoryField.getAnnotation(Autowired.class), "skillRepository must be @Autowired"); + } /* * Verifies that HomeController.processAddJobForm queries skillRepository and sets skills properly * */ -// @Test -// public void testProcessAddJobFormHandlesSkillsProperly ( -// @Mocked SkillRepository skillRepository, -// @Mocked EmployerRepository employerRepository, -// @Mocked JobRepository jobRepository, -// @Mocked Job job, -// @Mocked Errors errors) -// throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException { -// Class homeControllerClass = getClassByName("controllers.HomeController"); -// Method processAddJobFormMethod = homeControllerClass.getMethod("processAddJobForm", Job.class, Errors.class, Model.class, int.class, List.class); -// -// new Expectations() {{ -// skillRepository.findAllById((Iterable) any); -// job.setSkills((List) any); -// }}; -// -// Model model = new ExtendedModelMap(); -// HomeController homeController = new HomeController(); -// -// Field skillRepositoryField = homeControllerClass.getDeclaredField("skillRepository"); -// skillRepositoryField.setAccessible(true); -// skillRepositoryField.set(homeController, skillRepository); -// -// Field employerRepositoryField = homeControllerClass.getDeclaredField("employerRepository"); -// employerRepositoryField.setAccessible(true); -// employerRepositoryField.set(homeController, employerRepository); - -// Field jobRepositoryField = homeControllerClass.getDeclaredField("jobRepository"); -// jobRepositoryField.setAccessible(true); -// jobRepositoryField.set(homeController, jobRepository); -// -// processAddJobFormMethod.invoke(homeController, job, errors, model, 0, new ArrayList()); -// } + @Test + public void testProcessAddJobFormHandlesSkillsProperly ( + @Mocked SkillRepository skillRepository, + @Mocked EmployerRepository employerRepository, + @Mocked JobRepository jobRepository, + @Mocked Job job, + @Mocked Errors errors) + throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException { + Class homeControllerClass = getClassByName("controllers.HomeController"); + Method processAddJobFormMethod = homeControllerClass.getMethod("processAddJobForm", Job.class, Errors.class, Model.class, int.class, List.class); + + new Expectations() {{ + skillRepository.findAllById((List) any); + job.setSkills((List) any); + }}; + + Model model = new ExtendedModelMap(); + HomeController homeController = new HomeController(); + + Field skillRepositoryField = homeControllerClass.getDeclaredField("skillRepository"); + skillRepositoryField.setAccessible(true); + skillRepositoryField.set(homeController, skillRepository); + + Field employerRepositoryField = homeControllerClass.getDeclaredField("employerRepository"); + employerRepositoryField.setAccessible(true); + employerRepositoryField.set(homeController, employerRepository); + + Field jobRepositoryField = homeControllerClass.getDeclaredField("jobRepository"); + jobRepositoryField.setAccessible(true); + jobRepositoryField.set(homeController, jobRepository); + + processAddJobFormMethod.invoke(homeController, job, errors, model, 0, new ArrayList()); + } /* * Verifies that skillRepository and employerRepository fields have been added to ListController * */ -// @Test -// public void testListControllerHasAutowiredRepositories () throws ClassNotFoundException { -// Class listControllerClass = getClassByName("controllers.ListController"); -// Field employerRepositoryField = null; -// Field skillRepositoryField = null; -// -// try { -// employerRepositoryField = listControllerClass.getDeclaredField("employerRepository"); -// } catch (NoSuchFieldException e) { -// fail("ListController must have an employerRepository field"); -// } -// -// assertEquals(EmployerRepository.class, employerRepositoryField.getType()); -// assertNotNull(employerRepositoryField.getAnnotation(Autowired.class)); -// -// try { -// skillRepositoryField = listControllerClass.getDeclaredField("skillRepository"); -// } catch (NoSuchFieldException e) { -// fail("ListController must have a skillRepository field"); -// } -// -// assertEquals(SkillRepository.class, skillRepositoryField.getType()); -// assertNotNull(skillRepositoryField.getAnnotation(Autowired.class)); -// } + @Test + public void testListControllerHasAutowiredRepositories () throws ClassNotFoundException { + Class listControllerClass = getClassByName("controllers.ListController"); + Field employerRepositoryField = null; + Field skillRepositoryField = null; + + try { + employerRepositoryField = listControllerClass.getDeclaredField("employerRepository"); + } catch (NoSuchFieldException e) { + fail("ListController must have an employerRepository field"); + } + + assertEquals(EmployerRepository.class, employerRepositoryField.getType()); + assertNotNull(employerRepositoryField.getAnnotation(Autowired.class)); + + try { + skillRepositoryField = listControllerClass.getDeclaredField("skillRepository"); + } catch (NoSuchFieldException e) { + fail("ListController must have a skillRepository field"); + } + + assertEquals(SkillRepository.class, skillRepositoryField.getType()); + assertNotNull(skillRepositoryField.getAnnotation(Autowired.class)); + } /* * Verifies that ListController.list sets the correct model attributes using skill/employerRepository objects * */ -// @Test -// public void testListControllerListMethodSetsFormFieldData (@Mocked Model model, @Mocked SkillRepository skillRepository, @Mocked EmployerRepository employerRepository) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { -// Class listControllerClass = getClassByName("controllers.ListController"); -// ListController listController = new ListController(); -// -// new Expectations() {{ -// model.addAttribute("employers", any); -// model.addAttribute("skills", any); -// skillRepository.findAll(); -// employerRepository.findAll(); -// }}; -// -// Field skillRepositoryField = listControllerClass.getDeclaredField("skillRepository"); -// skillRepositoryField.setAccessible(true); -// skillRepositoryField.set(listController, skillRepository); -// -// Field employerRepositoryField = listControllerClass.getDeclaredField("employerRepository"); -// employerRepositoryField.setAccessible(true); -// employerRepositoryField.set(listController, employerRepository); -// -// listController.list(model); -// } + @Test + public void testListControllerListMethodSetsFormFieldData (@Mocked Model model, @Mocked SkillRepository skillRepository, @Mocked EmployerRepository employerRepository) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { + Class listControllerClass = getClassByName("controllers.ListController"); + ListController listController = new ListController(); + + new Expectations() {{ + model.addAttribute("employers", any); + model.addAttribute("skills", any); + skillRepository.findAll(); + employerRepository.findAll(); + }}; + + Field skillRepositoryField = listControllerClass.getDeclaredField("skillRepository"); + skillRepositoryField.setAccessible(true); + skillRepositoryField.set(listController, skillRepository); + + Field employerRepositoryField = listControllerClass.getDeclaredField("employerRepository"); + employerRepositoryField.setAccessible(true); + employerRepositoryField.set(listController, employerRepository); + + listController.list(model); + } @Test public void testSqlQuery () throws IOException { diff --git a/src/test/java/org/launchcode/techjobs/persistent/TestTaskThree.java b/src/test/java/org/launchcode/techjobs/persistent/TestTaskThree.java index 6a74962..9215914 100644 --- a/src/test/java/org/launchcode/techjobs/persistent/TestTaskThree.java +++ b/src/test/java/org/launchcode/techjobs/persistent/TestTaskThree.java @@ -7,6 +7,8 @@ import org.launchcode.techjobs.persistent.models.AbstractEntity; import org.launchcode.techjobs.persistent.models.Employer; import org.launchcode.techjobs.persistent.models.Job; +import org.launchcode.techjobs.persistent.models.data.EmployerRepository; +import org.launchcode.techjobs.persistent.models.data.SkillRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.Model; @@ -149,34 +151,34 @@ public void testHomeControllerUsesEmployerRepository() throws ClassNotFoundExcep /* * Verifies that HomeController.displayAddJobForm calls employerRepository.findAll() * */ -// @Test -// public void testHomeControllerFetchesEmployers(@Mocked EmployerRepository employerRepository, @Mocked SkillRepository skillRepository) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { -// Class homeControllerClass = getClassByName("controllers.HomeController"); -// HomeController homeController = new HomeController(); -// -// Field employerRepositoryField = homeControllerClass.getDeclaredField("employerRepository"); -// employerRepositoryField.setAccessible(true); -// employerRepositoryField.set(homeController, employerRepository); -// -// // not needed for verification, but necessary to make sure calling the controller -// // method doesn't throw a NullPointerException -// Field skillRepositoryField = null; -// try { -// skillRepositoryField = homeControllerClass.getDeclaredField("skillRepository"); -// skillRepositoryField.setAccessible(true); -// skillRepositoryField.set(homeController, skillRepository); -// } catch (NoSuchFieldException e) { -// // do nothing -// } -// -// Model model = new ExtendedModelMap(); -// -// new Expectations() {{ -// employerRepository.findAll(); -// }}; -// -// homeController.displayAddJobForm(model); -// } + @Test + public void testHomeControllerFetchesEmployers(@Mocked EmployerRepository employerRepository, @Mocked SkillRepository skillRepository) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { + Class homeControllerClass = getClassByName("controllers.HomeController"); + HomeController homeController = new HomeController(); + + Field employerRepositoryField = homeControllerClass.getDeclaredField("employerRepository"); + employerRepositoryField.setAccessible(true); + employerRepositoryField.set(homeController, employerRepository); + + // not needed for verification, but necessary to make sure calling the controller + // method doesn't throw a NullPointerException + Field skillRepositoryField = null; + try { + skillRepositoryField = homeControllerClass.getDeclaredField("skillRepository"); + skillRepositoryField.setAccessible(true); + skillRepositoryField.set(homeController, skillRepository); + } catch (NoSuchFieldException e) { + // do nothing + } + + Model model = new ExtendedModelMap(); + + new Expectations() {{ + employerRepository.findAll(); + }}; + + homeController.displayAddJobForm(model); + } /* * Tests SQL query for task 3 diff --git a/src/test/java/org/launchcode/techjobs/persistent/TestTaskTwo.java b/src/test/java/org/launchcode/techjobs/persistent/TestTaskTwo.java index c8164b4..770e614 100644 --- a/src/test/java/org/launchcode/techjobs/persistent/TestTaskTwo.java +++ b/src/test/java/org/launchcode/techjobs/persistent/TestTaskTwo.java @@ -4,8 +4,11 @@ import mockit.Mocked; import org.junit.jupiter.api.Test; import org.launchcode.techjobs.persistent.controllers.EmployerController; +import org.launchcode.techjobs.persistent.controllers.SkillController; import org.launchcode.techjobs.persistent.models.Employer; import org.launchcode.techjobs.persistent.models.Skill; +import org.launchcode.techjobs.persistent.models.data.EmployerRepository; +import org.launchcode.techjobs.persistent.models.data.SkillRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; @@ -330,213 +333,213 @@ public void testSkillRepositoryHasRepositoryAnnotation () throws ClassNotFoundEx /* * Verifies that the employerRepository field is correctly defined * */ -// @Test -// public void testEmployerRepositoryDefinition () throws ClassNotFoundException { -// Class employerController = getClassByName("controllers.EmployerController"); -// Field employerRepositoryField = null; -// -// try { -// employerRepositoryField = employerController.getDeclaredField("employerRepository"); -// } catch (NoSuchFieldException e) { -// fail("EmployerController does not have an employerRepository field"); -// } -// -// assertEquals(EmployerRepository.class, employerRepositoryField.getType(), "employerRepository must be of type EmployerRepository"); -// assertNotNull(employerRepositoryField.getAnnotation(Autowired.class), "employerRepository must have the @Autowired annotation"); -// } + @Test + public void testEmployerRepositoryDefinition () throws ClassNotFoundException { + Class employerController = getClassByName("controllers.EmployerController"); + Field employerRepositoryField = null; + + try { + employerRepositoryField = employerController.getDeclaredField("employerRepository"); + } catch (NoSuchFieldException e) { + fail("EmployerController does not have an employerRepository field"); + } + + assertEquals(EmployerRepository.class, employerRepositoryField.getType(), "employerRepository must be of type EmployerRepository"); + assertNotNull(employerRepositoryField.getAnnotation(Autowired.class), "employerRepository must have the @Autowired annotation"); + } /* * Verifies that EmployerController.index is properly defined * */ -// @Test -// public void testEmployerControllerIndexMethodDefinition (@Mocked EmployerRepository employerRepository) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException { -// Class employerControllerClass = getClassByName("controllers.EmployerController"); -// Method indexMethod = null; -// -// // Verify that the index method exists -// try { -// indexMethod = employerControllerClass.getMethod("index", Model.class); -// } catch (NoSuchMethodException e) { -// fail("EmployerController must have an index method that takes a parameter of type Model"); -// } -// -// Annotation annotation = indexMethod.getDeclaredAnnotation(RequestMapping.class); -// -// // Verify that index has a routing annotation. We need to accommodate -// // both @RequestMapping and @GetMapping. -// if (annotation == null) { -// annotation = indexMethod.getDeclaredAnnotation(GetMapping.class); -// } -// -// assertNotNull(annotation, "index method must have a routing annotation"); -// -// Method annotationValueMethod = annotation.getClass().getMethod("value"); -// String[] values = ((String[]) annotationValueMethod.invoke(annotation)); -// assertEquals(1, values.length, "The routing annotation for index must have a value"); -// assertEquals("", values[0], "The value parameter for the routing annotation must be the empty string"); -// -// // Verify that index calls employerRepository.findAll() -// new Expectations() {{ -// employerRepository.findAll(); -// }}; -// -// Model model = new ExtendedModelMap(); -// EmployerController employerController = new EmployerController(); -// Field employerRepositoryField = employerControllerClass.getDeclaredField("employerRepository"); -// employerRepositoryField.setAccessible(true); -// employerRepositoryField.set(employerController, employerRepository); -// indexMethod.invoke(employerController, model); -// } + @Test + public void testEmployerControllerIndexMethodDefinition (@Mocked EmployerRepository employerRepository) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException { + Class employerControllerClass = getClassByName("controllers.EmployerController"); + Method indexMethod = null; + + // Verify that the index method exists + try { + indexMethod = employerControllerClass.getMethod("index", Model.class); + } catch (NoSuchMethodException e) { + fail("EmployerController must have an index method that takes a parameter of type Model"); + } + + Annotation annotation = indexMethod.getDeclaredAnnotation(RequestMapping.class); + + // Verify that index has a routing annotation. We need to accommodate + // both @RequestMapping and @GetMapping. + if (annotation == null) { + annotation = indexMethod.getDeclaredAnnotation(GetMapping.class); + } + + assertNotNull(annotation, "index method must have a routing annotation"); + + Method annotationValueMethod = annotation.getClass().getMethod("value"); + String[] values = ((String[]) annotationValueMethod.invoke(annotation)); + assertEquals(1, values.length, "The routing annotation for index must have a value"); + assertEquals("", values[0], "The value parameter for the routing annotation must be the empty string"); + + // Verify that index calls employerRepository.findAll() + new Expectations() {{ + employerRepository.findAll(); + }}; + + Model model = new ExtendedModelMap(); + EmployerController employerController = new EmployerController(); + Field employerRepositoryField = employerControllerClass.getDeclaredField("employerRepository"); + employerRepositoryField.setAccessible(true); + employerRepositoryField.set(employerController, employerRepository); + indexMethod.invoke(employerController, model); + } /* * Verify that processAddEmployerForm saves a new employer to the database * */ -// @Test -// public void testNewEmployerIsSaved (@Mocked EmployerRepository employerRepository, @Mocked Errors errors) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException { -// Class employerControllerClass = getClassByName("controllers.EmployerController"); -// Method processAddEmployerFormMethod = employerControllerClass.getMethod("processAddEmployerForm", Employer.class, Errors.class, Model.class); -// Method saveMethod = EmployerRepository.class.getMethod("save", Object.class); -// -// Employer employer = new Employer(); -// employer.setLocation("Saint Louis"); -// employer.setName("LaunchCode"); -// -// new Expectations() {{ -// saveMethod.invoke(employerRepository, employer); -// }}; -// -// Model model = new ExtendedModelMap(); -// EmployerController employerController = new EmployerController(); -// Field employerRepositoryField = employerControllerClass.getDeclaredField("employerRepository"); -// employerRepositoryField.setAccessible(true); -// employerRepositoryField.set(employerController, employerRepository); -// processAddEmployerFormMethod.invoke(employerController, employer, errors, model); -// } + @Test + public void testNewEmployerIsSaved (@Mocked EmployerRepository employerRepository, @Mocked Errors errors) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException { + Class employerControllerClass = getClassByName("controllers.EmployerController"); + Method processAddEmployerFormMethod = employerControllerClass.getMethod("processAddEmployerForm", Employer.class, Errors.class, Model.class); + Method saveMethod = EmployerRepository.class.getMethod("save", Object.class); + + Employer employer = new Employer(); + employer.setLocation("Saint Louis"); + employer.setName("LaunchCode"); + + new Expectations() {{ + saveMethod.invoke(employerRepository, employer); + }}; + + Model model = new ExtendedModelMap(); + EmployerController employerController = new EmployerController(); + Field employerRepositoryField = employerControllerClass.getDeclaredField("employerRepository"); + employerRepositoryField.setAccessible(true); + employerRepositoryField.set(employerController, employerRepository); + processAddEmployerFormMethod.invoke(employerController, employer, errors, model); + } /* * Verifies that displayViewEmployer calls findById to retrieve an employer object * */ -// @Test -// public void testDisplayViewEmployerCallsFindById (@Mocked EmployerRepository employerRepository) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException { -// Class employerControllerClass = getClassByName("controllers.EmployerController"); -// Method displayViewEmployerMethod = employerControllerClass.getMethod("displayViewEmployer", Model.class, int.class); -// -// new Expectations() {{ -// employerRepository.findById(1); -// }}; -// -// Model model = new ExtendedModelMap(); -// EmployerController employerController = new EmployerController(); -// Field employerRepositoryField = employerControllerClass.getDeclaredField("employerRepository"); -// employerRepositoryField.setAccessible(true); -// employerRepositoryField.set(employerController, employerRepository); -// displayViewEmployerMethod.invoke(employerController, model, 1); -// } + @Test + public void testDisplayViewEmployerCallsFindById (@Mocked EmployerRepository employerRepository) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException { + Class employerControllerClass = getClassByName("controllers.EmployerController"); + Method displayViewEmployerMethod = employerControllerClass.getMethod("displayViewEmployer", Model.class, int.class); + + new Expectations() {{ + employerRepository.findById(1); + }}; + + Model model = new ExtendedModelMap(); + EmployerController employerController = new EmployerController(); + Field employerRepositoryField = employerControllerClass.getDeclaredField("employerRepository"); + employerRepositoryField.setAccessible(true); + employerRepositoryField.set(employerController, employerRepository); + displayViewEmployerMethod.invoke(employerController, model, 1); + } /* * Verifies that the skillRepository field is correctly defined * */ -// @Test -// public void testSkillRepositoryDefinition () throws ClassNotFoundException { -// Class skillController = getClassByName("controllers.SkillController"); -// Field skillRepositoryField = null; -// -// try { -// skillRepositoryField = skillController.getDeclaredField("skillRepository"); -// } catch (NoSuchFieldException e) { -// fail("SkillController does not have an skillRepository field"); -// } -// -// assertEquals(SkillRepository.class, skillRepositoryField.getType(), "skillRepository must be of type SkillRepository"); -// assertNotNull(skillRepositoryField.getAnnotation(Autowired.class), "skillRepository must have the @Autowired annotation"); -// } + @Test + public void testSkillRepositoryDefinition () throws ClassNotFoundException { + Class skillController = getClassByName("controllers.SkillController"); + Field skillRepositoryField = null; + + try { + skillRepositoryField = skillController.getDeclaredField("skillRepository"); + } catch (NoSuchFieldException e) { + fail("SkillController does not have an skillRepository field"); + } + + assertEquals(SkillRepository.class, skillRepositoryField.getType(), "skillRepository must be of type SkillRepository"); + assertNotNull(skillRepositoryField.getAnnotation(Autowired.class), "skillRepository must have the @Autowired annotation"); + } /* * Verifies that SkillController.index is properly defined * */ -// @Test -// public void testSkillControllerIndexMethodDefinition (@Mocked SkillRepository skillRepository) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException { -// Class skillControllerClass = getClassByName("controllers.SkillController"); -// Method indexMethod = null; -// -// // Verify that the index method exists -// try { -// indexMethod = skillControllerClass.getMethod("index", Model.class); -// } catch (NoSuchMethodException e) { -// fail("SkillController must have an index method that takes a parameter of type Model"); -// } -// -// Annotation annotation = indexMethod.getDeclaredAnnotation(RequestMapping.class); -// -// // Verify that index has a routing annotation. We need to accommodate -// // both @RequestMapping and @GetMapping. -// if (annotation == null) { -// annotation = indexMethod.getDeclaredAnnotation(GetMapping.class); -// } -// -// assertNotNull(annotation, "index method must have a routing annotation"); -// -// Method annotationValueMethod = annotation.getClass().getMethod("value"); -// String[] values = ((String[]) annotationValueMethod.invoke(annotation)); -// assertEquals(1, values.length, "The routing annotation for index must have a value"); -// assertEquals("", values[0], "The value parameter for the routing annotation must be the empty string"); -// -// // Verify that index calls skillRepository.findAll() -// new Expectations() {{ -// skillRepository.findAll(); -// }}; -// -// Model model = new ExtendedModelMap(); -// SkillController skillController = new SkillController(); -// Field skillRepositoryField = skillControllerClass.getDeclaredField("skillRepository"); -// skillRepositoryField.setAccessible(true); -// skillRepositoryField.set(skillController, skillRepository); -// indexMethod.invoke(skillController, model); -// } + @Test + public void testSkillControllerIndexMethodDefinition (@Mocked SkillRepository skillRepository) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException { + Class skillControllerClass = getClassByName("controllers.SkillController"); + Method indexMethod = null; + + // Verify that the index method exists + try { + indexMethod = skillControllerClass.getMethod("index", Model.class); + } catch (NoSuchMethodException e) { + fail("SkillController must have an index method that takes a parameter of type Model"); + } + + Annotation annotation = indexMethod.getDeclaredAnnotation(RequestMapping.class); + + // Verify that index has a routing annotation. We need to accommodate + // both @RequestMapping and @GetMapping. + if (annotation == null) { + annotation = indexMethod.getDeclaredAnnotation(GetMapping.class); + } + + assertNotNull(annotation, "index method must have a routing annotation"); + + Method annotationValueMethod = annotation.getClass().getMethod("value"); + String[] values = ((String[]) annotationValueMethod.invoke(annotation)); + assertEquals(1, values.length, "The routing annotation for index must have a value"); + assertEquals("", values[0], "The value parameter for the routing annotation must be the empty string"); + + // Verify that index calls skillRepository.findAll() + new Expectations() {{ + skillRepository.findAll(); + }}; + + Model model = new ExtendedModelMap(); + SkillController skillController = new SkillController(); + Field skillRepositoryField = skillControllerClass.getDeclaredField("skillRepository"); + skillRepositoryField.setAccessible(true); + skillRepositoryField.set(skillController, skillRepository); + indexMethod.invoke(skillController, model); + } /* * Verify that processAddSkillForm saves a new skill to the database * */ -// @Test -// public void testNewSkillIsSaved (@Mocked SkillRepository skillRepository, @Mocked Errors errors) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException { -// Class skillControllerClass = getClassByName("controllers.SkillController"); -// Method processAddSkillFormMethod = skillControllerClass.getMethod("processAddSkillForm", Skill.class, Errors.class, Model.class); -// Method saveMethod = SkillRepository.class.getMethod("save", Object.class); -// -// Skill skill = new Skill(); -// skill.setName("Java"); -// -// new Expectations() {{ -// saveMethod.invoke(skillRepository, skill); -// }}; -// -// Model model = new ExtendedModelMap(); -// SkillController skillController = new SkillController(); -// Field skillRepositoryField = skillControllerClass.getDeclaredField("skillRepository"); -// skillRepositoryField.setAccessible(true); -// skillRepositoryField.set(skillController, skillRepository); -// processAddSkillFormMethod.invoke(skillController, skill, errors, model); -// } + @Test + public void testNewSkillIsSaved (@Mocked SkillRepository skillRepository, @Mocked Errors errors) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException { + Class skillControllerClass = getClassByName("controllers.SkillController"); + Method processAddSkillFormMethod = skillControllerClass.getMethod("processAddSkillForm", Skill.class, Errors.class, Model.class); + Method saveMethod = SkillRepository.class.getMethod("save", Object.class); + + Skill skill = new Skill(); + skill.setName("Java"); + + new Expectations() {{ + saveMethod.invoke(skillRepository, skill); + }}; + + Model model = new ExtendedModelMap(); + SkillController skillController = new SkillController(); + Field skillRepositoryField = skillControllerClass.getDeclaredField("skillRepository"); + skillRepositoryField.setAccessible(true); + skillRepositoryField.set(skillController, skillRepository); + processAddSkillFormMethod.invoke(skillController, skill, errors, model); + } /* * Verifies that displayViewSkill calls findById to retrieve an skill object * */ -// @Test -// public void testDisplayViewSkillCallsFindById (@Mocked SkillRepository skillRepository) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException { -// Class skillControllerClass = getClassByName("controllers.SkillController"); -// Method displayViewSkillMethod = skillControllerClass.getMethod("displayViewSkill", Model.class, int.class); -// -// new Expectations() {{ -// skillRepository.findById(1); -// }}; -// -// Model model = new ExtendedModelMap(); -// SkillController skillController = new SkillController(); -// Field skillRepositoryField = skillControllerClass.getDeclaredField("skillRepository"); -// skillRepositoryField.setAccessible(true); -// skillRepositoryField.set(skillController, skillRepository); -// displayViewSkillMethod.invoke(skillController, model, 1); -// } + @Test + public void testDisplayViewSkillCallsFindById (@Mocked SkillRepository skillRepository) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException { + Class skillControllerClass = getClassByName("controllers.SkillController"); + Method displayViewSkillMethod = skillControllerClass.getMethod("displayViewSkill", Model.class, int.class); + + new Expectations() {{ + skillRepository.findById(1); + }}; + + Model model = new ExtendedModelMap(); + SkillController skillController = new SkillController(); + Field skillRepositoryField = skillControllerClass.getDeclaredField("skillRepository"); + skillRepositoryField.setAccessible(true); + skillRepositoryField.set(skillController, skillRepository); + displayViewSkillMethod.invoke(skillController, model, 1); + } // --- END CONTROLLER TESTS --- //