diff --git a/.github/workflows/backend-sonarqube-analysis.yml b/.github/workflows/backend-sonarqube-analysis.yml index 3375873c..ef1fcb99 100644 --- a/.github/workflows/backend-sonarqube-analysis.yml +++ b/.github/workflows/backend-sonarqube-analysis.yml @@ -40,7 +40,7 @@ jobs: cache: maven - name: mvn package - run: mvn -B verify --file backend/pom.xml + run: mvn -B clean verify --file backend/pom.xml - name: Cache SonarQube packages uses: actions/cache@v4 diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index d807d882..51a6a2fa 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -42,7 +42,7 @@ jobs: # only build relevant service - name: mvn package - run: mvn -B package --file backend/${{ matrix.service.directory }}/pom.xml + run: mvn -B clean package --file backend/${{ matrix.service.directory }}/pom.xml - name: Extract metadata (tags, labels) for Docker id: meta diff --git a/backend/app.hopps.org/src/main/java/app/hopps/org/jpa/TreeSearchBommel.java b/backend/app.hopps.org/src/main/java/app/hopps/org/jpa/TreeSearchBommel.java index b4fedf59..f5013dcf 100644 --- a/backend/app.hopps.org/src/main/java/app/hopps/org/jpa/TreeSearchBommel.java +++ b/backend/app.hopps.org/src/main/java/app/hopps/org/jpa/TreeSearchBommel.java @@ -1,12 +1,15 @@ package app.hopps.org.jpa; +import com.fasterxml.jackson.annotation.JsonIgnore; + import java.util.Arrays; import java.util.List; public record TreeSearchBommel( Bommel bommel, - boolean cycleMark, + @JsonIgnore boolean cycleMark, List cyclePath) { + public TreeSearchBommel(Bommel bommel, Boolean cycleMark, String cyclePath) { this(bommel, cycleMark != null && cycleMark, parseCyclePath(cyclePath)); } diff --git a/backend/app.hopps.org/src/main/resources/application.properties b/backend/app.hopps.org/src/main/resources/application.properties index 217e4030..c8d6c920 100644 --- a/backend/app.hopps.org/src/main/resources/application.properties +++ b/backend/app.hopps.org/src/main/resources/application.properties @@ -10,7 +10,8 @@ quarkus.banner.path=banner.txt quarkus.flyway.migrate-at-start=true quarkus.flyway.baseline-on-migrate=true quarkus.flyway.clean-at-start=false -# +%test.quarkus.flyway.locations=db/migration,db/testdata +%dev.quarkus.flyway.locations=db/migration,db/testdata ######################################## # Keycloak/auth ######################################## diff --git a/backend/app.hopps.org/src/main/resources/db/testdata/V2.0.0__test_data.sql b/backend/app.hopps.org/src/main/resources/db/testdata/V2.0.0__test_data.sql new file mode 100644 index 00000000..2e9e4826 --- /dev/null +++ b/backend/app.hopps.org/src/main/resources/db/testdata/V2.0.0__test_data.sql @@ -0,0 +1,104 @@ +insert into Organization (type, id, slug, name, website, plz, city, street, number) +values +(0, 2, 'gruenes-herz-ev', 'Grünes Herz e.V.', 'https://gruenes-herz.de/', '27324', 'Schweringen', 'Am Lennestein', '110'), +(0, 3, 'kaeltekrieger', 'Eishockeyclub Kältekrieger e.V.', 'https://kaeltekrieger.de/', '89129', 'Langenau', 'August-Brust-Straße', '78'), +(0, 4, 'buehnefrei-ev', 'Theatervereine Bühnefrei e.V.', 'https://bühnefrei.de/', '33397', 'Rietberg', 'Dechant-Karthaus-Straße', '172'); + +insert into member +(id, email, firstName, lastName) +values +-- gruenes-herz-ev +(2, 'emanuel_urban@domain.none', 'Emanuel', 'Urban'), +(3, 'hartlieb-reuter@xyz.none', 'Hartlieb', 'Reuter'), +(4, 'elgard-nicklas@trashmail.none', 'Elgard', 'Nicklas'), +(5, 'gerald.geiger@company.none', 'Gerald', 'Geiger'), +(6, 'jannick.1923@net-mail.none', 'Jannick', 'Cao'), +(7, 'constance.wendling@justmail.none', 'Constance', 'Wendling'), +(8, 'florenz-huefner@spam-mail.none', 'Florenz', 'Häfner'), +-- kaeltekrieger +(9, 'h1978@company.none', 'Herlind', 'Kutscher'), +(10, 'annekathrinfeldhoff@inter-mail.none', 'Annekathrin', 'Feldhof'), +(11, 'rosegunde-19@anymail.none', 'Rosegunde', 'Wilhelmy'), +(12, 'eckhardweirich@spam-mail.none', 'Eckhard', 'Weirich'), +(13, 'g_2011@inter-mail.none', 'Godo', 'Beckers'), +(14, 'klothilde1916@net-mail.none', 'Klothilde', 'Püppel'), +-- buehnefrei-ev +(15, 'samantha1284@net-mail.none', 'Samantha', 'Adomeit'), +(16, 'm-linner@private.none', 'Margund', 'Linner'), +(17, 'b-bork@mymail.none', 'Birgit', 'Bork'), +(18, 'gkalb@quickmail.none', 'Gunther', 'Kalb'), +(19, 'b-schlicker@trashmail.none', 'Burckhard', 'Schlicker'), +(20, 'alix1980@validmail.none', 'Alix', 'Raff'); + +insert into Member_Verein (member_id, organizations_id) +values +-- gruenes-herz-ev +(2, 2), +(3, 2), +(4, 2), +(5, 2), +(6, 2), +(7, 2), +(8, 2), +-- kaeltekrieger +(9, 3), +(10, 3), +(11, 3), +(12, 3), +(13, 3), +(14, 3), +-- buehnefrei-ev +(15, 4), +(16, 4), +(17, 4), +(18, 4), +(19, 4), +(20, 4); + +insert into Bommel (id, parent_id, name, emoji, responsibleMember_id) +values +-- gruenes-herz-ev (id=2) +(2, null, 'Grünes Herz e.V.', null, null), +(3, 2, 'Fundraising & Spenden', null, null), +(4, 2, 'Bildungs-Projekte', null, null), +(5, 2, 'Naturschutz-Projekte', null, null), +(6, 4, 'Schulvorträge', null, null), +(7, 4, 'Online Seminare', null, null), +(8, 6, 'Vortrag 1', null, null), +(9, 6, 'Vortrag 2', null, null), +(10, 5, 'Schutz eines Feuchte-Gebietes', null, null), +-- kaeltekrieger (id=3) +(11, null, 'Kältekrieger e.V.', null, null), +(12, 11, 'Verkauf', null, null), +(13, 11, 'Öffentlicher Lauf', null, null), +(14, 11, 'Mannschaften', null, null), +(15, 11, 'Stadion', null, null), +(16, 12, 'Kiosk', null, null), +(17, 12, 'Shop', null, null), +(18, 14, '1. Liga', null, null), +(19, 14, '2. Liga', null, null), +(20, 14, '3. Liga', null, null), +(21, 14, 'Jugend', null, null), +(22, 15, 'Eis Pflege', null, null), +-- buehnefrei-ev (id=4) +(23, null, 'Bühnefrei e.V.', null, null), +(24, 23, 'Kiosk', null, null), +(25, 23, 'Räumlichkeiten', null, null), +(26, 23, 'Workshops', null, null), +(27, 23, 'Projekte', null, null), +(28, 27, 'Der kleine Lord', null, null), +(29, 27, 'Das Hässliche Entlein', null, null), +(30, 27, 'König der Löwen', null, null) +; + +update Organization +set rootBommel_id = 2 +where id = 2; + +update Organization +set rootBommel_id = 11 +where id = 3; + +update Organization +set rootBommel_id = 23 +where id = 4; diff --git a/backend/app.hopps.org/src/test/java/app/hopps/org/delegates/CreationValidationDelegateTests.java b/backend/app.hopps.org/src/test/java/app/hopps/org/delegates/CreationValidationDelegateTests.java index a21fe168..b4d5aab4 100644 --- a/backend/app.hopps.org/src/test/java/app/hopps/org/delegates/CreationValidationDelegateTests.java +++ b/backend/app.hopps.org/src/test/java/app/hopps/org/delegates/CreationValidationDelegateTests.java @@ -107,7 +107,7 @@ void shouldValidateUniqueness() throws Exception { } @Test - @DisplayName("should validate valid data") + @DisplayName("should invalidate non-unique slug") void shouldInvalidateUniqueness() { // given @@ -117,6 +117,7 @@ void shouldInvalidateUniqueness() { existingOrganization.setSlug("kegelclub-777"); QuarkusTransaction.begin(); + organizationRepository.deleteAll(); organizationRepository.persist(existingOrganization); QuarkusTransaction.commit(); diff --git a/backend/app.hopps.org/src/test/java/app/hopps/org/delegates/PersistOrganizationDelegateTests.java b/backend/app.hopps.org/src/test/java/app/hopps/org/delegates/PersistOrganizationDelegateTests.java index 523ff7b5..5e6429d6 100644 --- a/backend/app.hopps.org/src/test/java/app/hopps/org/delegates/PersistOrganizationDelegateTests.java +++ b/backend/app.hopps.org/src/test/java/app/hopps/org/delegates/PersistOrganizationDelegateTests.java @@ -1,6 +1,10 @@ package app.hopps.org.delegates; -import app.hopps.org.jpa.*; +import app.hopps.org.jpa.BommelRepository; +import app.hopps.org.jpa.Member; +import app.hopps.org.jpa.MemberRepository; +import app.hopps.org.jpa.Organization; +import app.hopps.org.jpa.OrganizationRepository; import io.quarkus.test.junit.QuarkusTest; import jakarta.inject.Inject; import jakarta.transaction.Transactional; @@ -8,9 +12,7 @@ import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.*; import static org.hamcrest.collection.IsIterableWithSize.iterableWithSize; @QuarkusTest @@ -31,8 +33,8 @@ class PersistOrganizationDelegateTests { @BeforeEach @Transactional void cleanupDB() { - bommelRepository.deleteAll(); organizationRepository.deleteAll(); + bommelRepository.deleteAll(); memberRepository.deleteAll(); } diff --git a/backend/app.hopps.org/src/test/java/app/hopps/org/jpa/BommelTest.java b/backend/app.hopps.org/src/test/java/app/hopps/org/jpa/BommelTest.java index 5ce98ca3..2a8d94bd 100644 --- a/backend/app.hopps.org/src/test/java/app/hopps/org/jpa/BommelTest.java +++ b/backend/app.hopps.org/src/test/java/app/hopps/org/jpa/BommelTest.java @@ -5,6 +5,7 @@ import io.quarkus.test.TestTransaction; import io.quarkus.test.junit.QuarkusTest; import jakarta.inject.Inject; +import jakarta.transaction.Transactional; import jakarta.ws.rs.WebApplicationException; import org.flywaydb.core.Flyway; import org.instancio.Instancio; @@ -35,9 +36,10 @@ class BommelTest { Flyway flyway; @BeforeEach + @Transactional public void cleanDatabase() { - flyway.clean(); - flyway.migrate(); + orgRepo.deleteAll(); + repo.deleteAll(); } @Test @@ -106,14 +108,23 @@ void getChildrenWithCycle() { } @Test - @TestTransaction void simpleGetParentsTest() { // Arrange - var existingBommels = resourceCreator.setupSimpleTree(); - var expectedParentsList = List.of(existingBommels.get(1), existingBommels.getFirst()); + flyway.clean(); + flyway.migrate(); + + // bommel with id=2 is root + // id=4 is child of id=2 + // id=7 is child of id=4 + + var expectedParentsList = List.of( + repo.findById(4L), + repo.findById(2L)); + + var child = repo.findById(7L); // Act - List treeSearchParents = repo.getParents(existingBommels.get(3)); + List treeSearchParents = repo.getParents(child); // Assert var actualParents = treeSearchParents.stream() diff --git a/backend/app.hopps.org/src/test/java/app/hopps/org/rest/OrganizationResourceTests.java b/backend/app.hopps.org/src/test/java/app/hopps/org/rest/OrganizationResourceTests.java index d3620382..8742778a 100644 --- a/backend/app.hopps.org/src/test/java/app/hopps/org/rest/OrganizationResourceTests.java +++ b/backend/app.hopps.org/src/test/java/app/hopps/org/rest/OrganizationResourceTests.java @@ -1,6 +1,9 @@ package app.hopps.org.rest; +import app.hopps.org.jpa.BommelRepository; +import app.hopps.org.jpa.MemberRepository; import app.hopps.org.jpa.Organization; +import app.hopps.org.jpa.OrganizationRepository; import app.hopps.org.rest.model.NewOrganizationInput; import app.hopps.org.rest.model.OrganizationInput; import app.hopps.org.rest.model.OwnerInput; @@ -17,10 +20,8 @@ import java.net.MalformedURLException; import java.net.URI; -import java.util.Collections; import static io.restassured.RestAssured.given; -import static io.restassured.RestAssured.when; import static org.hamcrest.Matchers.*; @QuarkusTest @@ -30,6 +31,15 @@ class OrganizationResourceTests { @Inject Flyway flyway; + @Inject + OrganizationRepository organizationRepository; + + @Inject + MemberRepository memberRepository; + + @Inject + BommelRepository bommelRepository; + @BeforeEach public void cleanDatabase() { flyway.clean(); @@ -78,6 +88,12 @@ void shouldInvalidateVereinWithoutName() { @Test void shouldStartCreatingOrganization() throws MalformedURLException { + QuarkusTransaction.begin(); + organizationRepository.deleteAll(); + bommelRepository.deleteAll(); + memberRepository.deleteAll(); + QuarkusTransaction.commit(); + OrganizationInput organizationInput = new OrganizationInput("Schützenverein", "schuetzenverein", Organization.TYPE.EINGETRAGENER_VEREIN, URI.create("https://hopps.cloud").toURL(), URI.create("https://hopps.cloud").toURL(), null);