Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GET movie By Id #10

Merged
merged 11 commits into from
Aug 20, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
import de.webdev.backend.model.Movie;
import de.webdev.backend.service.MovieService;
import lombok.RequiredArgsConstructor;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;


import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/api/movies")
Expand All @@ -20,8 +24,19 @@ public List<Movie> getMovies() {
return movieService.getAllMovies();
}


@GetMapping("{id}")
public ResponseEntity<Movie> getMovieById(@PathVariable String id) {
Optional<Movie> movieOptional = Optional.ofNullable(movieService.getMovieById(id));
return movieOptional.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());

}


@PostMapping()
public Movie postMovie(@RequestBody MovieDto userEntries){
public Movie postMovie (@RequestBody MovieDto userEntries) {
return movieService.addMovie(userEntries);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

public interface MovieService {
List<Movie> getAllMovies();

Movie getMovieById(String id);
Movie addMovie(MovieDto userEntries);

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ public List<Movie> getAllMovies() {
return movieRepository.findAll();
}


@Override
public Movie getMovieById(String id) {
return movieRepository.findById(id).orElse(null);
}
@Override
public Movie addMovie(MovieDto userEntries){
Movie newMovie = new Movie(
Expand All @@ -31,5 +36,6 @@ public Movie addMovie(MovieDto userEntries){
);

return movieRepository.save(newMovie);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,53 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.http.MediaType;
import org.springframework.test.annotation.DirtiesContext;

import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;




import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;


@SpringBootTest
@AutoConfigureMockMvc
class MovieControllerTest {

@Autowired
private MockMvc mockMvc;



@Test
@DirtiesContext
void getMovie_shouldRetunEmptyList_whenCallInitially() throws Exception {
void getMovie_shouldReturnEmptyList_whenCallInitially() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/api/movies"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().json("[]"));
}

@Test
@DirtiesContext
void getMovieById_shouldReturnIsNotFound_whenMovieDoesNotExist() throws Exception {

mockMvc.perform(MockMvcRequestBuilders.get("/api/movies/1"))
.andExpect(MockMvcResultMatchers.status().isNotFound());
}

@Test
@DirtiesContext
void postMovie_shouldReturnANewMovie() throws Exception{
mockMvc.perform(MockMvcRequestBuilders
.post("/api/movies")
.contentType(MediaType.APPLICATION_JSON)
.content("""

{
"author": "exampleAuthor",
"title": "exampleTitle",
Expand All @@ -46,13 +62,14 @@ void postMovie_shouldReturnANewMovie() throws Exception{
))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().json("""

{
"author": "exampleAuthor",
"title": "exampleTitle",
"genre": "drama",
"publicationDate": "2023-08-16T14:30:00"
}
"""
"""
))
.andExpect(jsonPath("$.id").exists());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
Expand Down Expand Up @@ -36,6 +37,27 @@ void getAllMovies() {
verify(movieRepository).findAll();
}

@Test

void getMovieById_shouldReturnMovie_whenIdExists() {
Movie movie = new Movie("1", "First movie", "First author", "exampleGenre", publicationDate);
when(movieRepository.findById("1")).thenReturn(Optional.of(movie));

Movie actual = movieService.getMovieById("1");

assertEquals(movie, actual);
verify(movieRepository).findById("1");
}

@Test
void getMovieById_shouldReturnNull_whenIdDoesNotExist() {
when(movieRepository.findById("999")).thenReturn(Optional.empty());

Movie actual = movieService.getMovieById("999");

assertNull(actual);
verify(movieRepository).findById("999");
}
@Test
void addMovie() {

Expand All @@ -52,5 +74,6 @@ void addMovie() {

assertEquals(movie, result);


}
}
10 changes: 10 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import './App.css'
import ViewAllMovies from "./components/ViewAllMovies.tsx";
import MovieCard from "./components/MovieCard.tsx";
import NewMovieForm from "./components/NewMovieForm.tsx";
import {Route, Routes} from "react-router-dom";


function App() {



return (
<Routes>
<Route path="/movies" element={<ViewAllMovies/>}/>

<Route path="/movies/:id" element={<MovieCard/>}/>

<Route path="/movies/add" element={<NewMovieForm/>}/>

</Routes>
)
}
Expand Down
30 changes: 30 additions & 0 deletions frontend/src/components/MovieCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import axios from "axios";
import {useEffect, useState} from "react";
import {useParams} from "react-router-dom";
import {Movie} from "../models/movie.tsx";

export default function MovieCard() {
const {id} = useParams();
const [movie, setMovie] = useState({} as Movie);
async function fetchMovie() {
try {
const response = await axios.get(`/api/movies/${id}`);
setMovie(response.data);
} catch (error) {
console.error('Error fetching data:', error);
}
}

useEffect(() => {
fetchMovie();
}, [id]);
console.log(movie);
return (
<div>
<h2>Movie Title: {movie.title}</h2>
<p>Author: {movie.author}</p>
{/* <p>Genre: {movie.genre}</p>
<p>Date of publication: {movie.date}</p>*/}
</div>
)
}
17 changes: 12 additions & 5 deletions frontend/src/components/ViewAllMovies.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {useEffect,useState} from "react";
import {useEffect, useState} from "react";
import axios from 'axios';

import {Movie} from "../models/movie.tsx";
import {Link} from "react-router-dom";

export default function ViewAllMovies() {
const [movies, setMovies] = useState<Movie[]>([]);
const [movies, setMovies] = useState<Movie[]>([]);


const fetchData = () => {
axios.get('/api/movies')
Expand All @@ -20,11 +21,17 @@ export default function ViewAllMovies() {
fetchData();

}, []);


return (
<>
{movies.map((movie) => (
<h2 key={movie.id}>{movie.title} by {movie.author}</h2>
<div key={movie.id}>
<h2>{movie.title} by {movie.author}</h2>
<Link to={`/movies/${movie.id}`}>View Details</Link>
</div>
))}
</>
)
}
}

2 changes: 2 additions & 0 deletions frontend/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import './index.css'
import {BrowserRouter} from "react-router-dom";

createRoot(document.getElementById('root')!).render(

<StrictMode>
<BrowserRouter>
<App/>
</BrowserRouter>
</StrictMode>,

)
Loading