From 8d8ca047f5f98ba1cc5fbf1f8eaec9a02f29be65 Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:29:19 +0100 Subject: [PATCH 01/11] Use dw DataSize for validation --- .../conquery/models/config/ClusterConfig.java | 13 ++-- .../util/validation/DataSizeMaxValidator.java | 24 ++++++ .../util/validation/DataSizeMinValidator.java | 24 ++++++ .../conquery/io/mina/MinaStackTest.java | 2 +- .../validation/DataSizeValidationTest.java | 77 +++++++++++++++++++ 5 files changed, 133 insertions(+), 7 deletions(-) create mode 100644 backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMaxValidator.java create mode 100644 backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMinValidator.java create mode 100644 backend/src/test/java/com/bakdata/conquery/util/validation/DataSizeValidationTest.java diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ClusterConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ClusterConfig.java index e94c1ee3ce..db30c61c59 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/config/ClusterConfig.java +++ b/backend/src/main/java/com/bakdata/conquery/models/config/ClusterConfig.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.ObjectMapper; import io.dropwizard.core.Configuration; +import io.dropwizard.util.DataSize; import io.dropwizard.util.Duration; import io.dropwizard.validation.PortRange; import lombok.Getter; @@ -51,7 +52,7 @@ public class ClusterConfig extends Configuration { */ @Max(Integer.MAX_VALUE - 4) @Min(64) // not practical - private int maxIoBufferSizeBytes = Integer.MAX_VALUE - 4; + private DataSize maxIoBufferSize = DataSize.bytes(Integer.MAX_VALUE - 4); /** * Defines the starting buffer allocation size. Larger can reduce reallocations, but can cause a greater memory demand. @@ -60,7 +61,7 @@ public class ClusterConfig extends Configuration { */ @Max(Integer.MAX_VALUE - 4) @Min(64) // Mina's default - private int initialIoBufferSizeBytes = 8192; // 8kb + private DataSize initialIoBufferSize = DataSize.bytes(8192); // 8kb /** * @see com.bakdata.conquery.models.messages.namespaces.specific.CollectColumnValuesJob @@ -90,8 +91,8 @@ public NioSocketConnector getClusterConnector(ObjectMapper om, IoHandler ioHandl final NioSocketConnector connector = new NioSocketConnector(); JacksonProtocolEncoder encoder = new JacksonProtocolEncoder(om.writerFor(NetworkMessage.class)); - encoder.setMaxObjectSize(maxIoBufferSizeBytes); - encoder.setInitialBufferCapacityBytes(initialIoBufferSizeBytes); + encoder.setMaxObjectSize(Math.toIntExact(maxIoBufferSize.toBytes())); + encoder.setInitialBufferCapacityBytes(Math.toIntExact(initialIoBufferSize.toBytes())); ProtocolCodecFilter codecFilter = new ProtocolCodecFilter( encoder, @@ -115,8 +116,8 @@ public NioSocketAcceptor getClusterAcceptor(ObjectMapper om, IoHandler ioHandler JacksonProtocolEncoder encoder = new JacksonProtocolEncoder(om.writerFor(NetworkMessage.class)); - encoder.setMaxObjectSize(maxIoBufferSizeBytes); - encoder.setInitialBufferCapacityBytes(initialIoBufferSizeBytes); + encoder.setMaxObjectSize(Math.toIntExact(maxIoBufferSize.toBytes())); + encoder.setInitialBufferCapacityBytes(Math.toIntExact(initialIoBufferSize.toBytes())); ProtocolCodecFilter codecFilter = new ProtocolCodecFilter( encoder, diff --git a/backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMaxValidator.java b/backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMaxValidator.java new file mode 100644 index 0000000000..48ad48af15 --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMaxValidator.java @@ -0,0 +1,24 @@ +package com.bakdata.conquery.util.validation; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import jakarta.validation.constraints.Max; + +import com.google.auto.service.AutoService; +import io.dropwizard.util.DataSize; + +@AutoService(ConstraintValidator.class) +public class DataSizeMaxValidator implements ConstraintValidator { + + private long maxBytes; + + @Override + public void initialize(Max constraintAnnotation) { + maxBytes = constraintAnnotation.value(); + } + + @Override + public boolean isValid(DataSize value, ConstraintValidatorContext context) { + return value.toBytes() <= maxBytes; + } +} diff --git a/backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMinValidator.java b/backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMinValidator.java new file mode 100644 index 0000000000..d634cb2a19 --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMinValidator.java @@ -0,0 +1,24 @@ +package com.bakdata.conquery.util.validation; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import jakarta.validation.constraints.Min; + +import com.google.auto.service.AutoService; +import io.dropwizard.util.DataSize; + +@AutoService(ConstraintValidator.class) +public class DataSizeMinValidator implements ConstraintValidator { + + private long minBytes; + + @Override + public void initialize(Min constraintAnnotation) { + minBytes = constraintAnnotation.value(); + } + + @Override + public boolean isValid(DataSize value, ConstraintValidatorContext context) { + return value.toBytes() >= minBytes; + } +} diff --git a/backend/src/test/java/com/bakdata/conquery/io/mina/MinaStackTest.java b/backend/src/test/java/com/bakdata/conquery/io/mina/MinaStackTest.java index 56b44fad71..e7a79d1cf2 100644 --- a/backend/src/test/java/com/bakdata/conquery/io/mina/MinaStackTest.java +++ b/backend/src/test/java/com/bakdata/conquery/io/mina/MinaStackTest.java @@ -56,7 +56,7 @@ public class MinaStackTest { public static void beforeAll() throws IOException { CLUSTER_CONFIG.setPort(0); - CLUSTER_CONFIG.setMaxIoBufferSizeBytes(toIntExact(DataSize.mebibytes(10).toBytes())); + CLUSTER_CONFIG.setMaxIoBufferSize(DataSize.mebibytes(10)); // This enables the Chunking filter, which triggers for messages > 1 MebiByte CLUSTER_CONFIG.getMina().setSendBufferSize(toIntExact(DataSize.mebibytes(1).toBytes())); diff --git a/backend/src/test/java/com/bakdata/conquery/util/validation/DataSizeValidationTest.java b/backend/src/test/java/com/bakdata/conquery/util/validation/DataSizeValidationTest.java new file mode 100644 index 0000000000..ce4353ab0c --- /dev/null +++ b/backend/src/test/java/com/bakdata/conquery/util/validation/DataSizeValidationTest.java @@ -0,0 +1,77 @@ +package com.bakdata.conquery.util.validation; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Set; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validator; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; + +import io.dropwizard.jersey.validation.Validators; +import io.dropwizard.util.DataSize; +import lombok.Data; +import org.junit.jupiter.api.Test; + +public class DataSizeValidationTest { + + Validator VALIDATOR = Validators.newValidator(); + + + @Test + void inBounds() { + Container container = new Container(DataSize.bytes(5)); + + Set> validate = VALIDATOR.validate(container); + + assertThat(validate).isEmpty(); + + } + + @Test + void onMaxBound() { + Container container = new Container(DataSize.bytes(6)); + + Set> validate = VALIDATOR.validate(container); + + assertThat(validate).isEmpty(); + + } + + @Test + void onMinBound() { + Container container = new Container(DataSize.bytes(3)); + + Set> validate = VALIDATOR.validate(container); + + assertThat(validate).isEmpty(); + + } + + @Test + void maxedOut() { + Container container = new Container(DataSize.bytes(7)); + + Set> validate = VALIDATOR.validate(container); + + assertThat(validate).hasSize(1); + + } + + @Test + void minedOut() { + Container container = new Container(DataSize.bytes(2)); + + Set> validate = VALIDATOR.validate(container); + + assertThat(validate).hasSize(1); + + } + + @Data + private static class Container { + @Min(3) + @Max(6) + private final DataSize size; + } +} From 86f90f1d95820b04dbfdaaa2812fcac07c357e92 Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:38:32 +0100 Subject: [PATCH 02/11] use dw provided validators --- .../conquery/models/config/ClusterConfig.java | 12 +-- .../util/validation/DataSizeMaxValidator.java | 24 ------ .../util/validation/DataSizeMinValidator.java | 24 ------ .../validation/DataSizeValidationTest.java | 77 ------------------- 4 files changed, 7 insertions(+), 130 deletions(-) delete mode 100644 backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMaxValidator.java delete mode 100644 backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMinValidator.java delete mode 100644 backend/src/test/java/com/bakdata/conquery/util/validation/DataSizeValidationTest.java diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/ClusterConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/ClusterConfig.java index db30c61c59..6f963faaeb 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/config/ClusterConfig.java +++ b/backend/src/main/java/com/bakdata/conquery/models/config/ClusterConfig.java @@ -4,7 +4,6 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import jakarta.validation.Valid; -import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; @@ -17,7 +16,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.dropwizard.core.Configuration; import io.dropwizard.util.DataSize; +import io.dropwizard.util.DataSizeUnit; import io.dropwizard.util.Duration; +import io.dropwizard.validation.MaxDataSize; +import io.dropwizard.validation.MinDataSize; import io.dropwizard.validation.PortRange; import lombok.Getter; import lombok.Setter; @@ -50,8 +52,8 @@ public class ClusterConfig extends Configuration { *

* May only touch this for testing purposes. */ - @Max(Integer.MAX_VALUE - 4) - @Min(64) // not practical + @MaxDataSize(value = Integer.MAX_VALUE - 4, unit = DataSizeUnit.BYTES) + @MinDataSize(value = 64, unit = DataSizeUnit.BYTES) private DataSize maxIoBufferSize = DataSize.bytes(Integer.MAX_VALUE - 4); /** @@ -59,8 +61,8 @@ public class ClusterConfig extends Configuration { *

* May only touch this for testing purposes. */ - @Max(Integer.MAX_VALUE - 4) - @Min(64) // Mina's default + @MaxDataSize(value = Integer.MAX_VALUE - 4, unit = DataSizeUnit.BYTES) + @MinDataSize(value = 64, unit = DataSizeUnit.BYTES) private DataSize initialIoBufferSize = DataSize.bytes(8192); // 8kb /** diff --git a/backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMaxValidator.java b/backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMaxValidator.java deleted file mode 100644 index 48ad48af15..0000000000 --- a/backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMaxValidator.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.bakdata.conquery.util.validation; - -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; -import jakarta.validation.constraints.Max; - -import com.google.auto.service.AutoService; -import io.dropwizard.util.DataSize; - -@AutoService(ConstraintValidator.class) -public class DataSizeMaxValidator implements ConstraintValidator { - - private long maxBytes; - - @Override - public void initialize(Max constraintAnnotation) { - maxBytes = constraintAnnotation.value(); - } - - @Override - public boolean isValid(DataSize value, ConstraintValidatorContext context) { - return value.toBytes() <= maxBytes; - } -} diff --git a/backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMinValidator.java b/backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMinValidator.java deleted file mode 100644 index d634cb2a19..0000000000 --- a/backend/src/main/java/com/bakdata/conquery/util/validation/DataSizeMinValidator.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.bakdata.conquery.util.validation; - -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; -import jakarta.validation.constraints.Min; - -import com.google.auto.service.AutoService; -import io.dropwizard.util.DataSize; - -@AutoService(ConstraintValidator.class) -public class DataSizeMinValidator implements ConstraintValidator { - - private long minBytes; - - @Override - public void initialize(Min constraintAnnotation) { - minBytes = constraintAnnotation.value(); - } - - @Override - public boolean isValid(DataSize value, ConstraintValidatorContext context) { - return value.toBytes() >= minBytes; - } -} diff --git a/backend/src/test/java/com/bakdata/conquery/util/validation/DataSizeValidationTest.java b/backend/src/test/java/com/bakdata/conquery/util/validation/DataSizeValidationTest.java deleted file mode 100644 index ce4353ab0c..0000000000 --- a/backend/src/test/java/com/bakdata/conquery/util/validation/DataSizeValidationTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.bakdata.conquery.util.validation; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.Set; -import jakarta.validation.ConstraintViolation; -import jakarta.validation.Validator; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; - -import io.dropwizard.jersey.validation.Validators; -import io.dropwizard.util.DataSize; -import lombok.Data; -import org.junit.jupiter.api.Test; - -public class DataSizeValidationTest { - - Validator VALIDATOR = Validators.newValidator(); - - - @Test - void inBounds() { - Container container = new Container(DataSize.bytes(5)); - - Set> validate = VALIDATOR.validate(container); - - assertThat(validate).isEmpty(); - - } - - @Test - void onMaxBound() { - Container container = new Container(DataSize.bytes(6)); - - Set> validate = VALIDATOR.validate(container); - - assertThat(validate).isEmpty(); - - } - - @Test - void onMinBound() { - Container container = new Container(DataSize.bytes(3)); - - Set> validate = VALIDATOR.validate(container); - - assertThat(validate).isEmpty(); - - } - - @Test - void maxedOut() { - Container container = new Container(DataSize.bytes(7)); - - Set> validate = VALIDATOR.validate(container); - - assertThat(validate).hasSize(1); - - } - - @Test - void minedOut() { - Container container = new Container(DataSize.bytes(2)); - - Set> validate = VALIDATOR.validate(container); - - assertThat(validate).hasSize(1); - - } - - @Data - private static class Container { - @Min(3) - @Max(6) - private final DataSize size; - } -} From 4754f71caa3d83125d9d542adb5c0b82f8b324e7 Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:07:16 +0100 Subject: [PATCH 03/11] use plain object for exception mapping --- .../io/jetty/ConqueryErrorExceptionMapper.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/bakdata/conquery/io/jetty/ConqueryErrorExceptionMapper.java b/backend/src/main/java/com/bakdata/conquery/io/jetty/ConqueryErrorExceptionMapper.java index 50625b48d1..2589b828f8 100644 --- a/backend/src/main/java/com/bakdata/conquery/io/jetty/ConqueryErrorExceptionMapper.java +++ b/backend/src/main/java/com/bakdata/conquery/io/jetty/ConqueryErrorExceptionMapper.java @@ -1,6 +1,8 @@ package com.bakdata.conquery.io.jetty; import com.bakdata.conquery.models.error.ConqueryError; +import com.bakdata.conquery.models.error.SimpleErrorInfo; + import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.ext.ExceptionMapper; @@ -8,9 +10,11 @@ public class ConqueryErrorExceptionMapper implements ExceptionMapper { @Override public Response toResponse(ConqueryError exception) { - return Response.status(Response.Status.BAD_REQUEST.getStatusCode()) - .type(MediaType.APPLICATION_JSON_TYPE) - .entity(exception) - .build(); + SimpleErrorInfo plain = exception.asPlain(); + + return Response.status(Response.Status.BAD_REQUEST.getStatusCode()) + .type(MediaType.APPLICATION_JSON_TYPE) + .entity(plain) + .build(); } } From 5c7b2cfa38b607cabf747fd0c9ab400526ac00c4 Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:20:33 +0100 Subject: [PATCH 04/11] check if startQuery error is a string/message and use it instead --- .../jetty/ConqueryErrorExceptionMapper.java | 6 ++--- cypress/e2e/frontend/test_1_runQuery.cy.js | 24 +++++++++++++++++++ .../support/test_data/sid.secondaryId.json | 5 ++++ cypress/support/test_data/table1.csv | 4 ++-- cypress/support/test_data/table1.import.json | 6 +++++ cypress/support/test_data/table1.table.json | 5 ++++ frontend/src/js/query-runner/QueryRunner.tsx | 2 +- .../src/js/query-runner/QueryRunnerInfo.tsx | 6 ++++- .../QueryNodeActions.tsx | 1 + pom.xml | 3 +-- scripts/load_e2e_data.sh | 4 ++++ 11 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 cypress/support/test_data/sid.secondaryId.json diff --git a/backend/src/main/java/com/bakdata/conquery/io/jetty/ConqueryErrorExceptionMapper.java b/backend/src/main/java/com/bakdata/conquery/io/jetty/ConqueryErrorExceptionMapper.java index 2589b828f8..a6799fc534 100644 --- a/backend/src/main/java/com/bakdata/conquery/io/jetty/ConqueryErrorExceptionMapper.java +++ b/backend/src/main/java/com/bakdata/conquery/io/jetty/ConqueryErrorExceptionMapper.java @@ -1,12 +1,12 @@ package com.bakdata.conquery.io.jetty; -import com.bakdata.conquery.models.error.ConqueryError; -import com.bakdata.conquery.models.error.SimpleErrorInfo; - import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.ext.ExceptionMapper; +import com.bakdata.conquery.models.error.ConqueryError; +import com.bakdata.conquery.models.error.SimpleErrorInfo; + public class ConqueryErrorExceptionMapper implements ExceptionMapper { @Override public Response toResponse(ConqueryError exception) { diff --git a/cypress/e2e/frontend/test_1_runQuery.cy.js b/cypress/e2e/frontend/test_1_runQuery.cy.js index d20a199c3e..72db9db384 100644 --- a/cypress/e2e/frontend/test_1_runQuery.cy.js +++ b/cypress/e2e/frontend/test_1_runQuery.cy.js @@ -61,6 +61,30 @@ describe("Run query", () => { cy.get('@executionList').find('[data-test-id="project-item-delete-button"]').click(); cy.get('@executionList').contains('Anfrage jetzt löschen').click(); }); + + it("Check user error message", () => { + cy.get('[data-test-id="right-pane-container"] >div:visible').as("queryEditor"); + + // Drag concept to editor + cy.contains("MultiConnector").trigger("dragstart").trigger("dragleave"); + cy.get("@queryEditor") + .trigger("dragenter") + .trigger("dragover") + .trigger("drop") + .trigger("dragend"); + + // Switch to secondary id mode + cy.get("@queryEditor").contains("Secondary Id").click() + + // Exclude only concept from secondary id to create an invalid query + cy.get("@queryEditor").find('[data-test-id="secondary-id-toggle"]').click() + + // Start query + cy.get("@queryEditor").find('[data-test-id="query-runner-button"]').click(); + + // Check for specific user error message + cy.get('[data-test-id="query-runner"]').contains("Die ausgewählte Analyseebenen konnte in keinem der ausgewählten Konzepten gefunden werden.") + }) }); describe("Reference list", () => { diff --git a/cypress/support/test_data/sid.secondaryId.json b/cypress/support/test_data/sid.secondaryId.json new file mode 100644 index 0000000000..c903fd7e0c --- /dev/null +++ b/cypress/support/test_data/sid.secondaryId.json @@ -0,0 +1,5 @@ +{ + "description": "SecondaryId for Dicing", + "label": "Secondary Id", + "name": "sid" +} \ No newline at end of file diff --git a/cypress/support/test_data/table1.csv b/cypress/support/test_data/table1.csv index f2acb0ce6b..09cd0f2290 100644 --- a/cypress/support/test_data/table1.csv +++ b/cypress/support/test_data/table1.csv @@ -1,2 +1,2 @@ -id,STRING -1,abc \ No newline at end of file +id,sid,STRING +1,a,abc \ No newline at end of file diff --git a/cypress/support/test_data/table1.import.json b/cypress/support/test_data/table1.import.json index 281aac393e..cba65f8f41 100644 --- a/cypress/support/test_data/table1.import.json +++ b/cypress/support/test_data/table1.import.json @@ -8,6 +8,12 @@ "inputType": "STRING", "operation": "COPY" }, + { + "inputColumn": "sid", + "name": "sid", + "inputType": "STRING", + "operation": "COPY" + }, { "inputColumn": "STRING", "name": "STRING", diff --git a/cypress/support/test_data/table1.table.json b/cypress/support/test_data/table1.table.json index 8175103b5a..e43bb1e98e 100644 --- a/cypress/support/test_data/table1.table.json +++ b/cypress/support/test_data/table1.table.json @@ -5,6 +5,11 @@ "name": "id", "type": "STRING" }, + { + "name": "sid", + "type": "STRING", + "secondaryId": "sid" + }, { "name": "STRING", "type": "STRING" diff --git a/frontend/src/js/query-runner/QueryRunner.tsx b/frontend/src/js/query-runner/QueryRunner.tsx index 296b46be41..30ff07863b 100644 --- a/frontend/src/js/query-runner/QueryRunner.tsx +++ b/frontend/src/js/query-runner/QueryRunner.tsx @@ -67,7 +67,7 @@ const QueryRunner = ({ ); return ( - + { const { t } = useTranslation(); - if (queryRunner.startQuery.error) { + const error = queryRunner.startQuery.error + if (error) { + // Maybe use type guard here + if (typeof error === 'string' && error.trim().length > 0) + return { type: "error", value: error }; return { type: "error", value: t("queryRunner.startError") }; } else if (queryRunner.stopQuery.error) { return { type: "error", value: t("queryRunner.stopError") }; diff --git a/frontend/src/js/standard-query-editor/QueryNodeActions.tsx b/frontend/src/js/standard-query-editor/QueryNodeActions.tsx index 930efc0c52..39e1007a97 100644 --- a/frontend/src/js/standard-query-editor/QueryNodeActions.tsx +++ b/frontend/src/js/standard-query-editor/QueryNodeActions.tsx @@ -112,6 +112,7 @@ const QueryNodeActions = (props: Props) => { { e.stopPropagation(); props.onToggleSecondaryIdExclude(props.andIdx, props.orIdx); diff --git a/pom.xml b/pom.xml index 935b4718d3..77ac1b6926 100644 --- a/pom.xml +++ b/pom.xml @@ -48,8 +48,7 @@ org.apache.maven.plugins maven-compiler-plugin - ${java.required} - ${java.required} + ${java.required} true diff --git a/scripts/load_e2e_data.sh b/scripts/load_e2e_data.sh index 7ab6c404d0..9795ba6afe 100755 --- a/scripts/load_e2e_data.sh +++ b/scripts/load_e2e_data.sh @@ -33,6 +33,10 @@ echo "Creating mappings" curl --fail -X POST "$admin_api/datasets/dataset1/internToExtern" -H "$h_ct" -H "$h_auth" -d "@./cypress/support/test_data/mapping.mapping.json" sleep 3 +echo "Creating secondary ids" +curl --fail -X POST "$admin_api/datasets/dataset1/secondaryId" -H "$h_ct" -H "$h_auth" -d "@./cypress/support/test_data/sid.secondaryId.json" +sleep 1 + # TODO secondary ID echo "Creating tables" for table_json in `ls ./cypress/support/test_data/*.table.json` From 13774e776d8cc44e06b063d8f310b240ce71a38e Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:26:20 +0100 Subject: [PATCH 05/11] prettier --- frontend/src/js/query-runner/QueryRunnerInfo.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/js/query-runner/QueryRunnerInfo.tsx b/frontend/src/js/query-runner/QueryRunnerInfo.tsx index 9ba1e8bd58..35ebc8a165 100644 --- a/frontend/src/js/query-runner/QueryRunnerInfo.tsx +++ b/frontend/src/js/query-runner/QueryRunnerInfo.tsx @@ -20,10 +20,10 @@ interface PropsT { const useMessage = (queryRunner: QueryRunnerStateT) => { const { t } = useTranslation(); - const error = queryRunner.startQuery.error + const error = queryRunner.startQuery.error; if (error) { // Maybe use type guard here - if (typeof error === 'string' && error.trim().length > 0) + if (typeof error === "string" && error.trim().length > 0) return { type: "error", value: error }; return { type: "error", value: t("queryRunner.startError") }; } else if (queryRunner.stopQuery.error) { From 8e057e9961de3063fb57de086221c2b07f869b93 Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:34:56 +0100 Subject: [PATCH 06/11] remove unnecessary comment --- scripts/load_e2e_data.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/load_e2e_data.sh b/scripts/load_e2e_data.sh index 9795ba6afe..fd31706c22 100755 --- a/scripts/load_e2e_data.sh +++ b/scripts/load_e2e_data.sh @@ -37,7 +37,6 @@ echo "Creating secondary ids" curl --fail -X POST "$admin_api/datasets/dataset1/secondaryId" -H "$h_ct" -H "$h_auth" -d "@./cypress/support/test_data/sid.secondaryId.json" sleep 1 - # TODO secondary ID echo "Creating tables" for table_json in `ls ./cypress/support/test_data/*.table.json` do From 1efaa8bc5114e652536877c2b673a67a6b8211fc Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:39:59 +0100 Subject: [PATCH 07/11] Respect request locale for error and start test browser (chromium) with de_DE locale --- .../com/bakdata/conquery/models/error/ConqueryError.java | 5 +++-- cypress/plugins/index.js | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java b/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java index ca21fc24d5..4776520c58 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java +++ b/backend/src/main/java/com/bakdata/conquery/models/error/ConqueryError.java @@ -2,12 +2,14 @@ import java.util.Set; import java.util.UUID; +import jakarta.validation.constraints.NotNull; import c10n.C10N; import com.bakdata.conquery.io.cps.CPSBase; import com.bakdata.conquery.io.cps.CPSType; import com.bakdata.conquery.models.forms.util.Alignment; import com.bakdata.conquery.models.forms.util.Resolution; +import com.bakdata.conquery.models.i18n.I18n; import com.bakdata.conquery.models.identifiable.ids.Id; import com.bakdata.conquery.models.query.entity.Entity; import com.bakdata.conquery.util.VariableDefaultValue; @@ -15,7 +17,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonTypeInfo; -import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.Getter; import lombok.NoArgsConstructor; @@ -79,7 +80,7 @@ public final String getCode() { @JsonIgnore @ToString.Include public final String getMessage() { - return getMessageTemplate(C10N.get(ErrorMessages.class)); + return getMessageTemplate(C10N.get(ErrorMessages.class, I18n.LOCALE.get())); } @JsonIgnore diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index 59b2bab6e4..4c119e1b59 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -19,4 +19,11 @@ module.exports = (on, config) => { // `on` is used to hook into various events Cypress emits // `config` is the resolved Cypress config + on('before:browser:launch', (browser = {}, launchOptions) => { + if (browser.family === 'chromium') { + launchOptions.args.push('--lang=de_DE'); + } + return launchOptions; + }); + } From 83fcb9f4fbac09fa1de50c3658676eb21d8a425a Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:57:34 +0100 Subject: [PATCH 08/11] set language for electron in cypress action --- .github/workflows/test_cypress.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test_cypress.yml b/.github/workflows/test_cypress.yml index c8d2e6525f..8977b37d9d 100644 --- a/.github/workflows/test_cypress.yml +++ b/.github/workflows/test_cypress.yml @@ -14,6 +14,9 @@ on: jobs: test: runs-on: ubuntu-latest + env: + # Set electron language to german so request use "accept-language: de" header + ELECTRON_EXTRA_LAUNCH_ARGS: --lang=de timeout-minutes: 10 steps: - name: Cache local Maven repository From 4b8d866fbc12e234609e8f4447a16fec3163465c Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Fri, 24 Jan 2025 15:21:48 +0100 Subject: [PATCH 09/11] combine query execution test case as they are not independent --- cypress/e2e/frontend/test_1_runQuery.cy.js | 10 +++++----- .../previous-queries/list/DeleteProjectItemButton.tsx | 1 + frontend/src/js/previous-queries/list/ProjectItem.tsx | 2 ++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/cypress/e2e/frontend/test_1_runQuery.cy.js b/cypress/e2e/frontend/test_1_runQuery.cy.js index d20a199c3e..50e7f69f37 100644 --- a/cypress/e2e/frontend/test_1_runQuery.cy.js +++ b/cypress/e2e/frontend/test_1_runQuery.cy.js @@ -12,7 +12,7 @@ describe("Run query", () => { visitWithToken(USER_TOKEN_WITH_PERMISSIONS); }); - it("Can execute query and see it in the queries tab", () => { + it("Can execute query, see it in the queries tab and delete it", () => { cy.get('[data-test-id="right-pane-container"] >div:visible').as("queryEditor"); // Drag concept to editor @@ -40,18 +40,16 @@ describe("Run query", () => { cy.get("@queryEditor").find('[data-test-id="query-runner-button"]').click(); cy.get("@queryEditor").contains("Ergebnisse"); - }); - it("Can see the executed query in the queries tab", () => { + // Lookup executed query in the previous queries tab cy.get('[data-test-id="left-pane"]').contains("Anfragen").click(); cy.get('[data-test-id="left-pane-container"]').as("leftPaneContainer"); cy.get("@leftPaneContainer").contains("Ergebnisse"); cy.get("@leftPaneContainer").contains("Concept1"); - }); - it("Can delete the query", () => { + // Delete the Query cy.get('[data-test-id="left-pane"]').contains("Anfragen").click(); cy.get('[data-test-id="left-pane-container"]').as("leftPaneContainer"); @@ -60,6 +58,8 @@ describe("Run query", () => { cy.get('@executionList').find('[data-test-id="project-item-delete-button"]').click(); cy.get('@executionList').contains('Anfrage jetzt löschen').click(); + + cy.get('@leftPaneContainer').contains('Keine Anfragen / Formulare gefunden') }); }); diff --git a/frontend/src/js/previous-queries/list/DeleteProjectItemButton.tsx b/frontend/src/js/previous-queries/list/DeleteProjectItemButton.tsx index 7ea16ca053..05b3a56f9c 100644 --- a/frontend/src/js/previous-queries/list/DeleteProjectItemButton.tsx +++ b/frontend/src/js/previous-queries/list/DeleteProjectItemButton.tsx @@ -41,6 +41,7 @@ export const DeleteProjectItemButton = ({ item }: { item: ProjectItemT }) => { diff --git a/frontend/src/js/previous-queries/list/ProjectItem.tsx b/frontend/src/js/previous-queries/list/ProjectItem.tsx index 700d15cde6..10c578011e 100644 --- a/frontend/src/js/previous-queries/list/ProjectItem.tsx +++ b/frontend/src/js/previous-queries/list/ProjectItem.tsx @@ -276,6 +276,8 @@ const ProjectItem = forwardRef< From e06a22ff82c5512e0fe1ec2e5ec1991a39dd8f28 Mon Sep 17 00:00:00 2001 From: Max Thonagel <12283268+thoniTUB@users.noreply.github.com> Date: Fri, 24 Jan 2025 15:31:34 +0100 Subject: [PATCH 10/11] prevent nasty NoSuchElementExceptionMapper if no preview config was submitted --- .../conquery/models/datasets/PreviewConfig.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/bakdata/conquery/models/datasets/PreviewConfig.java b/backend/src/main/java/com/bakdata/conquery/models/datasets/PreviewConfig.java index a3639bbee3..f57ee2c03e 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/datasets/PreviewConfig.java +++ b/backend/src/main/java/com/bakdata/conquery/models/datasets/PreviewConfig.java @@ -117,14 +117,14 @@ public record TimeStratifiedSelects(@NotNull String label, String description, @ @JsonIgnore public boolean isSelectsUnique() { return timeStratifiedSelects.stream().map(TimeStratifiedSelects::selects).flatMap(Collection::stream).map(InfoCardSelect::select).distinct().count() - == timeStratifiedSelects.stream().map(TimeStratifiedSelects::selects).flatMap(Collection::stream).count(); + == timeStratifiedSelects.stream().map(TimeStratifiedSelects::selects).mapToLong(Collection::size).sum(); } @ValidationMethod(message = "Labels must be unique.") @JsonIgnore public boolean isLabelsUnique() { return timeStratifiedSelects.stream().map(TimeStratifiedSelects::selects).flatMap(Collection::stream).map(InfoCardSelect::label).distinct().count() - == timeStratifiedSelects.stream().map(TimeStratifiedSelects::selects).flatMap(Collection::stream).count(); + == timeStratifiedSelects.stream().map(TimeStratifiedSelects::selects).mapToLong(Collection::size).sum(); } @JsonIgnore @@ -178,7 +178,7 @@ public String resolveSelectLabel(SelectResultInfo info) { public Listresolve) + .map(SelectId::resolve) .collect(Collectors.toList()); } @@ -200,10 +200,10 @@ public ConceptId resolveSearchConcept() { return searchFilters.stream() - .map(FilterId::>resolve) + .map(FilterId::resolve) .map(filter -> filter.getConnector().getConcept()) .distinct() .map(Concept::getId) - .collect(MoreCollectors.onlyElement()); + .collect(MoreCollectors.toOptional()).orElse(null); } } From f617bb602cdf96dd346a94353891e2ca5d75fc9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Jan 2025 04:47:52 +0000 Subject: [PATCH 11/11] Bump com.auth0:java-jwt from 4.2.2 to 4.5.0 Bumps [com.auth0:java-jwt](https://github.com/auth0/java-jwt) from 4.2.2 to 4.5.0. - [Release notes](https://github.com/auth0/java-jwt/releases) - [Changelog](https://github.com/auth0/java-jwt/blob/master/CHANGELOG.md) - [Commits](https://github.com/auth0/java-jwt/compare/4.2.2...4.5.0) --- updated-dependencies: - dependency-name: com.auth0:java-jwt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- backend/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/pom.xml b/backend/pom.xml index 198455f9b4..f09fc83cf0 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -295,7 +295,7 @@ com.auth0 java-jwt - 4.2.2 + 4.5.0 io.dropwizard