Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,13 @@ const getKliniker = async () => {

Visar alla djur som tillhör den inloggade djurägaren.

**`GET /pets/owner/{ownerId}`**
**`GET /api/pets/owner/{ownerId}`**

```javascript
const getMinaDjur = async () => {
const ownerId = 'c3d4e5f6-a7b8-4c5d-0e1f-a2b3c4d5e6f7'; // Annas ID

const response = await fetch(`http://localhost:8080/pets/owner/${ownerId}`, {
const response = await fetch(`http://localhost:8080/api/pets/owner/${ownerId}`, {
headers: {
'X-Dev-User': 'anna@test.se'
}
Expand Down Expand Up @@ -170,11 +170,11 @@ const getMinaDjur = async () => {

Registrera ett nytt djur för den inloggade ägaren.

**`POST /pets`**
**`POST /api/pets`**

```javascript
const skapaDjur = async () => {
const response = await fetch('http://localhost:8080/pets', {
const response = await fetch('http://localhost:8080/api/pets', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Expand Down Expand Up @@ -657,15 +657,15 @@ Kolumnen "Auth" visar vem som kan anropa endpointen.
{ "id": "uuid", "name": "...", "address": "...", "phoneNumber": "..." }
```

### Djur (`/pets`)
### Djur (`/api/pets`)

| Metod | URL | Auth | Beskrivning | Request body |
|-------|-----|------|-------------|--------------|
| POST | `/pets` | OWNER/ADMIN (Policy) | Skapa djur. Admin kan ange `?ownerId=uuid` | `{ name, species, breed, dateOfBirth, weightKg }` |
| GET | `/pets/{petId}` | OWNER/VET/ADMIN (Policy) | Hamta ett djur | — |
| GET | `/pets/owner/{ownerId}` | OWNER/ADMIN (Policy) | Hamta alla djur for en ägare | — |
| PUT | `/pets/{petId}` | OWNER/ADMIN (Policy) | Uppdatera djurinfo | `{ name, species, breed, dateOfBirth, weightKg }` |
| DELETE | `/pets/{petId}` | OWNER/ADMIN (Policy) | Ta bort djur | — |
| POST | `/api/pets` | OWNER/ADMIN (Policy) | Skapa djur. Admin kan ange `?ownerId=uuid` | `{ name, species, breed, dateOfBirth, weightKg }` |
| GET | `/api/pets/{petId}` | OWNER/VET/ADMIN (Policy) | Hamta ett djur | — |
| GET | `/api/pets/owner/{ownerId}` | OWNER/ADMIN (Policy) | Hamta alla djur for en ägare | — |
| PUT | `/api/pets/{petId}` | OWNER/ADMIN (Policy) | Uppdatera djurinfo | `{ name, species, breed, dateOfBirth, weightKg }` |
| DELETE | `/api/pets/{petId}` | OWNER/ADMIN (Policy) | Ta bort djur | — |

**Svar (PetResponse):**
```json
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import java.util.UUID;

@RestController
@RequestMapping("/pets")
@RequestMapping("/api/pets")
public class PetController {

private static final Logger log = LoggerFactory.getLogger(PetController.class);
Expand Down
74 changes: 30 additions & 44 deletions src/test/java/org/example/vet1177/controller/PetControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ private RequestPostProcessor authenticatedAs(User user) {
void createPet_shouldReturn200WithPetResponse() throws Exception {
when(petService.createPet(any(), any(), any())).thenReturn(pet);

mockMvc.perform(post("/pets")
mockMvc.perform(post("/api/pets")
.with(authenticatedAs(owner))
.header("currentUserId", ownerId)

.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(validPetRequest())))
.andExpect(status().isOk())
Expand All @@ -108,9 +108,9 @@ void createPet_whenInvalidRequest_shouldReturn400() throws Exception {
PetRequest request = validPetRequest();
request.setName("");

mockMvc.perform(post("/pets")
mockMvc.perform(post("/api/pets")
.with(authenticatedAs(owner))
.header("currentUserId", ownerId)

.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isBadRequest());
Expand All @@ -121,9 +121,9 @@ void createPet_whenForbidden_shouldReturn403() throws Exception {
when(petService.createPet(any(), any(), any()))
.thenThrow(new ForbiddenException("Du kan inte lägga till ett djur"));

mockMvc.perform(post("/pets")
mockMvc.perform(post("/api/pets")
.with(authenticatedAs(vet))
.header("currentUserId", UUID.randomUUID())

.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(validPetRequest())))
.andExpect(status().isForbidden());
Expand All @@ -134,9 +134,9 @@ void createPet_whenUnexpectedError_shouldReturn500() throws Exception {
when(petService.createPet(any(), any(), any()))
.thenThrow(new RuntimeException("Unexpected failure"));

mockMvc.perform(post("/pets")
mockMvc.perform(post("/api/pets")
.with(authenticatedAs(owner))
.header("currentUserId", ownerId)

.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(validPetRequest())))
.andExpect(status().isInternalServerError());
Expand All @@ -145,37 +145,31 @@ void createPet_whenUnexpectedError_shouldReturn500() throws Exception {

@Test
void getPetById_shouldReturn200WithPetResponse() throws Exception {
when(userService.getUserEntityById(any())).thenReturn(owner);
when(petService.getPetById(any(), any())).thenReturn(pet);

mockMvc.perform(get("/pets/{petId}", petId)
.with(authenticatedAs(owner))
.header("currentUserId", ownerId))
mockMvc.perform(get("/api/pets/{petId}", petId)
.with(authenticatedAs(owner)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Molly"));
}

@Test
void getPetById_whenNotFound_shouldReturn404() throws Exception {
when(userService.getUserEntityById(any())).thenReturn(owner);
when(petService.getPetById(any(), any()))
.thenThrow(new ResourceNotFoundException("Pet", petId));

mockMvc.perform(get("/pets/{petId}", petId)
.with(authenticatedAs(owner))
.header("currentUserId", ownerId))
mockMvc.perform(get("/api/pets/{petId}", petId)
.with(authenticatedAs(owner)))
.andExpect(status().isNotFound());
}

@Test
void getPetById_whenForbidden_shouldReturn403() throws Exception {
when(userService.getUserEntityById(any())).thenReturn(vet);
when(petService.getPetById(any(), any()))
.thenThrow(new ForbiddenException("Du har inte behörighet att se detta djur"));

mockMvc.perform(get("/pets/{petId}", petId)
.with(authenticatedAs(vet))
.header("currentUserId", UUID.randomUUID()))
mockMvc.perform(get("/api/pets/{petId}", petId)
.with(authenticatedAs(vet)))
.andExpect(status().isForbidden());
}
// GET /pets/owner/{ownerId}
Expand All @@ -184,9 +178,8 @@ void getPetById_whenForbidden_shouldReturn403() throws Exception {
void getPetsByOwner_shouldReturn200WithList() throws Exception {
when(petService.getPetsByOwner(any(), any())).thenReturn(List.of(pet));

mockMvc.perform(get("/pets/owner/{ownerId}", ownerId)
.with(authenticatedAs(owner))
.header("currentUserId", ownerId))
mockMvc.perform(get("/api/pets/owner/{ownerId}", ownerId)
.with(authenticatedAs(owner)))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].name").value("Molly"));
}
Expand All @@ -196,9 +189,8 @@ void getPetsByOwner_whenForbidden_shouldReturn403() throws Exception {
when(petService.getPetsByOwner(any(), any()))
.thenThrow(new ForbiddenException("Du saknar behörighet"));

mockMvc.perform(get("/pets/owner/{ownerId}", ownerId)
.with(authenticatedAs(vet))
.header("currentUserId", UUID.randomUUID()))
mockMvc.perform(get("/api/pets/owner/{ownerId}", ownerId)
.with(authenticatedAs(vet)))
.andExpect(status().isForbidden());
}

Expand All @@ -209,9 +201,9 @@ void updatePet_shouldReturn200WithUpdatedPetResponse() throws Exception {
Pet updated = new Pet(owner, "Harry", "Katt", "Siamese", LocalDate.of(2021, 3, 5), new BigDecimal("5.00"));
when(petService.updatePet(any(), any(), any())).thenReturn(updated);

mockMvc.perform(put("/pets/{petId}", petId)
mockMvc.perform(put("/api/pets/{petId}", petId)
.with(authenticatedAs(owner))
.header("currentUserId", ownerId)

.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(validPetRequest())))
.andExpect(status().isOk())
Expand All @@ -223,9 +215,9 @@ void updatePet_whenNotFound_shouldReturn404() throws Exception {
when(petService.updatePet(any(), any(), any()))
.thenThrow(new ResourceNotFoundException("Pet", petId));

mockMvc.perform(put("/pets/{petId}", petId)
mockMvc.perform(put("/api/pets/{petId}", petId)
.with(authenticatedAs(owner))
.header("currentUserId", ownerId)

.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(validPetRequest())))
.andExpect(status().isNotFound());
Expand All @@ -236,9 +228,9 @@ void updatePet_whenForbidden_shouldReturn403() throws Exception {
when(petService.updatePet(any(), any(), any()))
.thenThrow(new ForbiddenException("Du saknar behörighet"));

mockMvc.perform(put("/pets/{petId}", petId)
mockMvc.perform(put("/api/pets/{petId}", petId)
.with(authenticatedAs(vet))
.header("currentUserId", UUID.randomUUID())

.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(validPetRequest())))
.andExpect(status().isForbidden());
Expand All @@ -249,36 +241,30 @@ void updatePet_whenForbidden_shouldReturn403() throws Exception {

@Test
void deletePet_shouldReturn204() throws Exception {
when(userService.getUserEntityById(any())).thenReturn(owner);
doNothing().when(petService).deletePet(any(), any());

mockMvc.perform(delete("/pets/{petId}", petId)
.with(authenticatedAs(owner))
.header("currentUserId", ownerId))
mockMvc.perform(delete("/api/pets/{petId}", petId)
.with(authenticatedAs(owner)))
.andExpect(status().isNoContent());
}

@Test
void deletePet_whenNotFound_shouldReturn404() throws Exception {
when(userService.getUserEntityById(any())).thenReturn(owner);
doThrow(new ResourceNotFoundException("Pet", petId))
.when(petService).deletePet(any(), any());

mockMvc.perform(delete("/pets/{petId}", petId)
.with(authenticatedAs(owner))
.header("currentUserId", ownerId))
mockMvc.perform(delete("/api/pets/{petId}", petId)
.with(authenticatedAs(owner)))
.andExpect(status().isNotFound());
}

@Test
void deletePet_whenForbidden_shouldReturn403() throws Exception {
when(userService.getUserEntityById(any())).thenReturn(vet);
doThrow(new ForbiddenException("Du har inte behörighet att radera detta djur"))
.when(petService).deletePet(any(), any());

mockMvc.perform(delete("/pets/{petId}", petId)
.with(authenticatedAs(vet))
.header("currentUserId", UUID.randomUUID()))
mockMvc.perform(delete("/api/pets/{petId}", petId)
.with(authenticatedAs(vet)))
.andExpect(status().isForbidden());
}

Expand Down