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
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,16 @@ public ResponseEntity<ErrorResponse> handleConstraintViolation(ConstraintViolati

return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(org.springframework.web.bind.MissingRequestHeaderException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleMissingHeader(org.springframework.web.bind.MissingRequestHeaderException ex) {

log.warn("Missing header: {}", ex.getHeaderName());

return new ErrorResponse(
400,
"Missing required header: " + ex.getHeaderName(),
null
);
}
}
67 changes: 67 additions & 0 deletions src/test/java/org/example/vet1177/integration/TestDataFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package org.example.vet1177.integration;

import org.example.vet1177.entities.*;
import org.example.vet1177.repository.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.UUID;

public class TestDataFactory {

public static Clinic createClinic(ClinicRepository clinicRepository) {
Clinic clinic = new Clinic();
clinic.setName("Test Clinic " + UUID.randomUUID());
return clinicRepository.save(clinic);
}

public static User createOwner(UserRepository userRepository, Clinic clinic) {
User owner = new User(
"Owner",
UUID.randomUUID() + "@test.com",
"password123",
Role.OWNER,
clinic
);
return userRepository.save(owner);
}

public static Pet createPet(PetRepository petRepository, User owner) {
Pet pet = new Pet(
owner,
"Doggo",
"Dog",
"Labrador",
LocalDate.of(2020, 1, 1),
new BigDecimal("20.5")
);
return petRepository.save(pet);
}

public static MedicalRecord createRecord(
MedicalRecordRepository medicalRecordRepository,
User owner,
Clinic clinic,
Pet pet
) {
MedicalRecord record = new MedicalRecord();
record.setTitle("Test Record");
record.setOwner(owner);
record.setClinic(clinic);
record.setCreatedBy(owner);
record.setPet(pet);

return medicalRecordRepository.save(record);
}

public static ActivityLog createLog(
ActivityLogRepository repo,
User user,
MedicalRecord record,
ActivityType type,
String desc
) {
ActivityLog log = new ActivityLog(type, desc, user, record);
return repo.save(log);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
package org.example.vet1177.integration.activitylog;

import org.checkerframework.checker.units.qual.C;
import org.example.vet1177.config.AwsS3Properties;
import org.example.vet1177.entities.*;
import org.example.vet1177.integration.TestDataFactory;
import org.example.vet1177.repository.*;
import org.example.vet1177.services.FileStorageService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.UUID;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
@TestPropertySource(properties = {
"spring.datasource.url=jdbc:h2:mem:testdb;MODE=PostgreSQL",
"spring.datasource.driver-class-name=org.h2.Driver"
})
public class ActivityLogIntegrationTest {

@Autowired
private ClinicRepository clinicRepository;

@Autowired
private UserRepository userRepository;

@Autowired
private MedicalRecordRepository medicalRecordRepository;

@Autowired
private ActivityLogRepository activityLogRepository;
@Autowired
private MockMvc mockMvc;
@Autowired
private PetRepository petRepository;

@MockitoBean
private FileStorageService fileStorageService;

@MockitoBean
private AwsS3Properties awsS3Properties;


// @Test
// void should_return_logs_for_owner_only() throws Exception{
// //Arrange
// //1. Skapa klinik
// Clinic clinic = new Clinic();
// clinic.setName("Test Clinic");
// clinic = clinicRepository.save(clinic);
//
// //2. Skapa owner user
// User owner = new User(
// "Owner Test",
// "owner@test.com",
// "password123",
// Role.OWNER,
// clinic
// );
// owner = userRepository.save(owner);
//
// Pet pet = new Pet(
// owner,
// "Doggo",
// "Dog",
// "Labrador",
// LocalDate.of(2020, 1, 1),
// new BigDecimal("20.5")
// );
//
// pet = petRepository.save(pet);
//
//
// // 3. Skapa medical record
// MedicalRecord record = new MedicalRecord();
// record.setTitle("Test Record");
// record.setOwner(owner);
// record.setClinic(clinic);
// record.setCreatedBy(owner);
// record.setPet(pet);
// record = medicalRecordRepository.save(record);
//
// // 4. skapa activity logs
// ActivityLog log1 = new ActivityLog(
// ActivityType.CASE_CREATED,
// "First log",
// owner,
// record
// );
//
// ActivityLog log2 = new ActivityLog(
// ActivityType.UPDATED,
// "Second log",
// owner,
// record
// );
//
// activityLogRepository.save(log1);
// activityLogRepository.save(log2);
//
// // Act och Assert
// mockMvc.perform(get("/api/activity-logs/record/" + record.getId())
// .header("userId", owner.getId().toString()))
// .andExpect(status().isOk())
// .andExpect(jsonPath("$.length()").value(2));
// }
@Test
void should_return_logs_for_owner_only() throws Exception {

// Arrange
Clinic clinic = TestDataFactory.createClinic(clinicRepository);
User owner = TestDataFactory.createOwner(userRepository, clinic);
Pet pet = TestDataFactory.createPet(petRepository, owner);
MedicalRecord record = TestDataFactory.createRecord(
medicalRecordRepository, owner, clinic, pet
);

TestDataFactory.createLog(activityLogRepository, owner, record,
ActivityType.CASE_CREATED, "First log");

TestDataFactory.createLog(activityLogRepository, owner, record,
ActivityType.UPDATED, "Second log");

// Act & Assert
mockMvc.perform(get("/api/activity-logs/record/" + record.getId())
.header("userId", owner.getId().toString()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.length()").value(2));
}

@Test
void should_allow_vet_in_same_clinic_to_see_logs() throws Exception {

Clinic clinic = TestDataFactory.createClinic(clinicRepository);

User owner = TestDataFactory.createOwner(userRepository, clinic);
User vet = new User(
"Vet",
"vet@test.com",
"password",
Role.VET,
clinic
);
vet = userRepository.save(vet);

Pet pet = TestDataFactory.createPet(petRepository, owner);
MedicalRecord record = TestDataFactory.createRecord(
medicalRecordRepository, owner, clinic, pet
);

TestDataFactory.createLog(activityLogRepository, owner, record,
ActivityType.CASE_CREATED, "log");

mockMvc.perform(get("/api/activity-logs/record/" + record.getId())
.header("userId", vet.getId().toString()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.length()").value(1));
}

@Test
void should_filter_out_logs_for_vet_in_other_clinic() throws Exception {

Clinic clinicA = TestDataFactory.createClinic(clinicRepository);
Clinic clinicB = TestDataFactory.createClinic(clinicRepository);

User owner = TestDataFactory.createOwner(userRepository, clinicA);

User vetOtherClinic = new User(
"Vet",
"vet2@test.com",
"password",
Role.VET,
clinicB
);
vetOtherClinic = userRepository.save(vetOtherClinic);

Pet pet = TestDataFactory.createPet(petRepository, owner);
MedicalRecord record = TestDataFactory.createRecord(
medicalRecordRepository, owner, clinicA, pet
);

TestDataFactory.createLog(activityLogRepository, owner, record,
ActivityType.CASE_CREATED, "log");

mockMvc.perform(get("/api/activity-logs/record/" + record.getId())
.header("userId", vetOtherClinic.getId().toString()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.length()").value(0));
}

@Test
void should_return_400_if_userId_missing() throws Exception {

mockMvc.perform(get("/api/activity-logs/record/" + UUID.randomUUID()))
.andExpect(status().isBadRequest());
}
}
17 changes: 11 additions & 6 deletions src/test/resources/application-test.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,28 @@
# ============================================

# Separat testdatabas ? aldrig dev-databasen
spring.datasource.url=jdbc:postgresql://localhost:5432/vet1177_test
spring.datasource.username=vet1177_user
spring.datasource.password=vet1177_pass
spring.datasource.url=jdbc:h2:mem:testdb;MODE=PostgreSQL
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

spring.datasource.hikari.driver-class-name=org.h2.Driver

# Skapa schema fr�n scratch och rensa efter tester
spring.jpa.hibernate.ddl-auto=create-drop

# K�r schema.sql men INTE data.sql
spring.sql.init.mode=always
# Hibernate creates schema automatically (schema.sql is NOT used in tests)
spring.sql.init.mode=never
spring.sql.init.data-locations=
Comment thread
coderabbitai[bot] marked this conversation as resolved.

# St�ng av Docker Compose i tester
# CI hanterar databasen som service container
spring.docker.compose.lifecycle-management=none

# MinIO ? testbucket
aws.s3.endpoint=http://localhost:9000
aws.s3.endpoint=
aws.s3.access-key=minioadmin
aws.s3.secret-key=minioadmin
aws.s3.bucket-name=vet1177-test-attachments
Expand Down