From 62aa6854a763e4f6467cdce5d97a82c785fbb1b4 Mon Sep 17 00:00:00 2001 From: Gematik Date: Tue, 3 Dec 2024 06:43:01 +0100 Subject: [PATCH] Release 1.4.1 --- .gitignore | 2 +- ReleaseNotes.md | 23 +- doc/userguide/GettingStarted.adoc | 46 ++++ pom.xml | 23 +- .../tim/test/glue/api/GeneralStepsGlue.java | 7 - .../test/glue/api/TestdriverApiEndpoint.java | 6 + .../tim/test/glue/api/TestdriverApiPath.java | 4 +- .../tim/test/glue/api/TransferGlue.java | 196 ++++++++++++++---- .../authorization/AddAllowedDomainsTask.java | 47 +++++ .../authorization/AddBlockedDomainsTask.java | 47 +++++ .../api/authorization/AuthorizationGlue.java | 58 ++++++ .../DeleteAllowedDomainsTask.java | 47 +++++ .../DeleteBlockedDomainsTask.java | 47 +++++ .../practitioner/FhirAdministrationGlue.java | 2 +- .../DownloadAuthenticatedMediaQuestion.java | 49 +++++ .../tim/test/glue/api/media/MediaGlue.java | 54 +++-- .../api/message/MessageControllerGlue.java | 7 + .../glue/api/room/RoomControllerGlue.java | 34 ++- .../test/glue/api/room/UseRoomAbility.java | 2 +- .../glue/api/room/tasks/InviteToRoomTask.java | 3 +- .../tim/test/glue/api/utils/GlueUtils.java | 1 + .../resources/api/TiMessengerTestTreiber.yaml | 33 ++- 22 files changed, 653 insertions(+), 85 deletions(-) create mode 100644 src/main/java/de/gematik/tim/test/glue/api/authorization/AddAllowedDomainsTask.java create mode 100644 src/main/java/de/gematik/tim/test/glue/api/authorization/AddBlockedDomainsTask.java create mode 100644 src/main/java/de/gematik/tim/test/glue/api/authorization/DeleteAllowedDomainsTask.java create mode 100644 src/main/java/de/gematik/tim/test/glue/api/authorization/DeleteBlockedDomainsTask.java create mode 100644 src/main/java/de/gematik/tim/test/glue/api/media/DownloadAuthenticatedMediaQuestion.java diff --git a/.gitignore b/.gitignore index 80349e8..736fe76 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,7 @@ src/test/resources/templates/FeatureFiles/TI-M_11X/ZusatztestsOrgOnly/ src/test/resources/templates/FeatureFiles/TI-M_11X/Zusatztests/ src/test/resources/templates/FeatureFiles/TI-M_Abwaertskompatibilitaet_vs11X/ src/test/resources/templates/FeatureFiles/TIM_V2/ -src/test/resources/templates/Spielwiese +src/test/resources/templates/Spielwiese/ .owaspignore diff --git a/ReleaseNotes.md b/ReleaseNotes.md index cf0970c..87393ba 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -2,15 +2,26 @@ # Release notes -## Link to TI-Messenger-testsuite [`docu`](https://github.com/gematik/TI-Messenger-Testsuite/tree/main/doc/userguide/Testsuite.adoc#docu) +## Link to TI-Messenger-testsuite [ + +`docu`](https://github.com/gematik/TI-Messenger-Testsuite/tree/main/doc/userguide/Testsuite.adoc#docu) + +## Release 1.4.1 + +### Changes + +- adds functionality for add and delete domains in block/allow lists +- API change, breaking only ePa: renames deleteBlockedDomain to deleteBlockedUserDomain for consistency ## Release 1.4.0 ### Changes - adds 400 Bad Request responses for test driver api -- Adjustment for 03_AenderungEinesHealthcareService.json - Only one day of availableTime due to VZD change -- API breaking change: renames FhirAvailableTimes to FhirAvailableTime and adjusts description and example to reflect +- Adjustment for 03_AenderungEinesHealthcareService.json - Only one day of availableTime due to VZD + change +- API breaking change: renames FhirAvailableTimes to FhirAvailableTime and adjusts description and + example to reflect VZD update to profile 0.11.18 ### Bugs @@ -24,7 +35,8 @@ - Two unused endpoints were removed from the test driver API: getLocations, getLocation - Adjusts the blockedUsers and allowedUsers endpoints to allow code generation -- Three unused endpoints were removed from the test driver API: createLocation, updateLocation, deleteLocation +- Three unused endpoints were removed from the test driver API: createLocation, updateLocation, + deleteLocation ### Bugs @@ -336,7 +348,8 @@ - HttpTimout for serentiy set to 5 minutes. Can be configured by -DhttpTimeout=\ - If a claim device fails, the testsuite will retry to claim up to 3 times (configurable via environment - variable [`read more (Parameter die das Verhalten der Testsuite anpassen)`](doc/userguide/GettingStarted.adoc) + variable [ + `read more (Parameter die das Verhalten der Testsuite anpassen)`](doc/userguide/GettingStarted.adoc) ### Bugfixes diff --git a/doc/userguide/GettingStarted.adoc b/doc/userguide/GettingStarted.adoc index b7a3fd1..06eb86c 100644 --- a/doc/userguide/GettingStarted.adoc +++ b/doc/userguide/GettingStarted.adoc @@ -198,6 +198,52 @@ From must start with http:// and match the value in link:{sourcedir}/test/resour Make sure that the specified URL ends with a trailing '/', otherwise the connection will fail. <3> Additional resources in the path must be specified. +=== Correct Completion of the Metadata for the Interface + +IMPORTANT: Please ensure that the interface metadata is populated with all +required parameters accurately. + +One of these parameters is the information interface, which requires the +OS information. This parameter must be filled with the corresponding +operating system. This applies equally to both the TI-M client interface +(`clientInfo`) and the organization admin interface (`fachdienstInfo`). + +For the TI-M client interface, the operating system must be differentiated between: + +- Mobile clients (e.g., Android, iOS) +- Native clients (e.g., Windows, macOS) +- Web clients (e.g., Linux Server, Windows Server) + +The same applies to the organization admin interface. If it is +integrated into a TI-M client (e.g., within a native app), the operating +system should be specified similarly to TI-M clients (e.g., Windows, macOS). + +Client interface example: +---- +"clientInfo": { + "osInfo": { + "operatingSystem": "Android", + "version": "10" + } + } +---- +Organisation admin interface example: +---- +"fachdienstInfo": { + "osInfo": { + "operatingSystem": "LinuxServer", + "version": "5.15" + } + } +---- +Please ensure that all required parameters are filled in, not just the `osInfo` field! + +Additionally, this parameter must also be populated when using the same codebase for +multiple products requiring approval. It must align with the information +provided in the submitted application for approval documents. + +Example: In the application for approval: TI-M Client Android -> `"operatingSystem": "Android"`. + === Starting the test cases The test suite executes the tests as Maven integration tests. diff --git a/pom.xml b/pom.xml index 1215892..e6ce2a7 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ de.gematik.tim.test TI-Messenger-Testsuite - 1.4.0 + 1.4.1 jar TI-Messenger-Testsuite Testsuite to check functionality of TI-Messenger-Clients @@ -749,7 +749,7 @@ - false + true ^git.branch @@ -820,6 +820,19 @@ + + move-git-properties + initialize + + + + + + + run + + move_simulator_jar pre-integration-test @@ -916,7 +929,7 @@ cp -a - ${project.build.directory}/site/serenity/ + ${project.build.directory}/site/serenity/. ${basedir}/reports/${build.time}/report/ @@ -1037,7 +1050,7 @@ cp -a - ${project.build.directory}/site/serenity/ + ${project.build.directory}/site/serenity/. ${basedir}/reports/${build.time}/report/ @@ -1113,7 +1126,7 @@ cp -a - ${project.build.directory}/site/serenity/ + ${project.build.directory}/site/serenity/. ${basedir}/reports/${build.time}/report/ diff --git a/src/main/java/de/gematik/tim/test/glue/api/GeneralStepsGlue.java b/src/main/java/de/gematik/tim/test/glue/api/GeneralStepsGlue.java index a14b910..08f8fd7 100644 --- a/src/main/java/de/gematik/tim/test/glue/api/GeneralStepsGlue.java +++ b/src/main/java/de/gematik/tim/test/glue/api/GeneralStepsGlue.java @@ -24,7 +24,6 @@ import de.gematik.tim.test.glue.api.utils.TestcasePropertiesManager; import io.cucumber.java.de.Dann; import io.cucumber.java.en.Then; -import org.springframework.http.HttpStatus; public class GeneralStepsGlue { @@ -41,10 +40,4 @@ public static void checkResponseCode(String actorName, int responseCode) { } } } - - public static void checkResponseCode() { - if (!HttpStatus.valueOf(lastResponse().statusCode()).is2xxSuccessful()) { - throw new TestRunException("Operation returned error code " + lastResponse().statusCode()); - } - } } diff --git a/src/main/java/de/gematik/tim/test/glue/api/TestdriverApiEndpoint.java b/src/main/java/de/gematik/tim/test/glue/api/TestdriverApiEndpoint.java index f27f261..65e5acf 100644 --- a/src/main/java/de/gematik/tim/test/glue/api/TestdriverApiEndpoint.java +++ b/src/main/java/de/gematik/tim/test/glue/api/TestdriverApiEndpoint.java @@ -22,6 +22,7 @@ import static de.gematik.tim.test.glue.api.TestdriverApiEndpoint.HttpMethod.PUT; import static de.gematik.tim.test.glue.api.TestdriverApiPath.ACCOUNT_PATH; import static de.gematik.tim.test.glue.api.TestdriverApiPath.ALLOWED_USERS_PATH; +import static de.gematik.tim.test.glue.api.TestdriverApiPath.AUTHENTICATED_MEDIA_DOWNLOAD_PATH; import static de.gematik.tim.test.glue.api.TestdriverApiPath.AUTHORIZATION_PATH; import static de.gematik.tim.test.glue.api.TestdriverApiPath.BLOCKED_USERS_PATH; import static de.gematik.tim.test.glue.api.TestdriverApiPath.CLAIM_DEVICE_PATH; @@ -179,6 +180,7 @@ public enum TestdriverApiEndpoint { // MEDIA UPLOAD_MEDIA(POST, MEDIA_PATH, UseDeviceAbility.class), DOWNLOAD_MEDIA(GET, MEDIA_DOWNLOAD_PATH, UseDeviceAbility.class), + DOWNLOAD_AUTHENTICATED_MEDIA(GET, AUTHENTICATED_MEDIA_DOWNLOAD_PATH, UseDeviceAbility.class), // CONTACT-MANAGEMENT GET_CONTACT(GET, CONTACT_PATH, UseDeviceAbility.class), @@ -191,6 +193,10 @@ public enum TestdriverApiEndpoint { ADD_BLOCKED_USERS(POST, BLOCKED_USERS_PATH, UseDeviceAbility.class), ADD_ALLOWED_USERS(POST, ALLOWED_USERS_PATH, UseDeviceAbility.class), + ADD_ALLOWED_DOMAINS(POST, ALLOWED_USERS_PATH, UseDeviceAbility.class), + ADD_BLOCKED_DOMAINS(POST, BLOCKED_USERS_PATH, UseDeviceAbility.class), + DELETE_ALLOWED_DOMAINS(DELETE, ALLOWED_USERS_PATH, UseDeviceAbility.class), + DELETE_BLOCKED_DOMAINS(DELETE, BLOCKED_USERS_PATH, UseDeviceAbility.class), DELETE_BLOCKED_USERS(DELETE, BLOCKED_USERS_PATH, UseDeviceAbility.class), DELETE_ALLOWED_USERS(DELETE, ALLOWED_USERS_PATH, UseDeviceAbility.class); diff --git a/src/main/java/de/gematik/tim/test/glue/api/TestdriverApiPath.java b/src/main/java/de/gematik/tim/test/glue/api/TestdriverApiPath.java index f4fdf76..022c7b6 100644 --- a/src/main/java/de/gematik/tim/test/glue/api/TestdriverApiPath.java +++ b/src/main/java/de/gematik/tim/test/glue/api/TestdriverApiPath.java @@ -101,10 +101,12 @@ public final class TestdriverApiPath { // MEDIA public static final String MEDIA_PATH = DEVICE_ID_PATH + "/media"; - public static final String MEDIA_DOWNLOAD_PATH = MEDIA_PATH + "/" + PATH_VARIABLE.formatted(MEDIA_ID_VARIABLE); + public static final String AUTHENTICATED_MEDIA_DOWNLOAD_PATH = + MEDIA_PATH + "/authenticated/" + PATH_VARIABLE.formatted(MEDIA_ID_VARIABLE); + // AUTHORIZATION public static final String AUTHORIZATION_PATH = DEVICE_ID_PATH + "/authorizationMode"; public static final String BLOCKED_USERS_PATH = DEVICE_ID_PATH + "/blockedUsers"; diff --git a/src/main/java/de/gematik/tim/test/glue/api/TransferGlue.java b/src/main/java/de/gematik/tim/test/glue/api/TransferGlue.java index e082419..8356161 100644 --- a/src/main/java/de/gematik/tim/test/glue/api/TransferGlue.java +++ b/src/main/java/de/gematik/tim/test/glue/api/TransferGlue.java @@ -19,94 +19,216 @@ import static lombok.AccessLevel.PRIVATE; import io.cucumber.java.de.Dann; -import io.cucumber.java.de.Wenn; import java.util.List; + +import io.cucumber.java.en.Then; import lombok.AllArgsConstructor; @AllArgsConstructor(access = PRIVATE) public class TransferGlue { - @Dann("{string} hinterlegt die Domain von {listOfStrings} in der Blockliste") - public void putDomainInBlockList(String actorNames, List blockedUsers) { + @Dann( + "{listOfStrings} hinterlegt auf dem HomeServer sein Dehydrated Device inkl speichern des Schlüsselmaterials") + @Dann( + "{listOfStrings} hinterlegen auf dem HomeServer ihre Dehydrated Device inkl speichern des Schlüsselmaterials") + public void postDehydratedDevice(List actorNames) { // implement me } - @Dann("{string} entfernt die Domain von {listOfStrings} in der Blockliste") - public void deleteDomainInBlockList(String actorNames, List blockedUsers) { + @Dann("{listOfStrings} haben {string} Dehydrated Device auf dem HomeServer hinterlegt") + @Dann("{listOfStrings} hat {string} Dehydrated Device auf dem HomeServer hinterlegt") + public void getDehydratedDevices(List actorNames, String keineODERein) { // implement me } - @Dann("{string} hinterlegt die Domain von {listOfStrings} in der Allowliste") - public void putDomainInAllowList(String actorNames, List blockedUsers) { + @Dann("{listOfStrings} holt sich entschlüsselt sein Dehydrated Device vom HomeServer ab") + @Dann("{listOfStrings} holen sich entschlüsselt ihre Dehydrated Device vom HomeServer ab") + public void getBackDehydratedDevices(List actorNames) { // implement me } - // Noch nicht in gebrauch, wird aber kommen :) - @Dann("{string} entfernt die Domain von {listOfStrings} in der Allowliste") - public void deleteDomainInAllowList(String actorNames, List blockedUsers) { + @Dann("{string} findet {listOfStrings} in FHIR über die FDV-Schnittstelle") + public void findPractitionFromEpaClient(String actor, List actorNames) { // implement me } - @Wenn("{string} sendet ein Attachment {string} an den Raum {string} über Matrix-Protokoll v1.11") - public void sendetEinAttachmentAnDenRaumÜberMatrixProtokollV( - String arg0, String arg1, String arg2) { + @Dann("{string} findet {string} im Healthcare-Service {string} über die FDV-Schnittstelle") + public void findHCSFromEpaClient(String actor, List endpointUser, String hcsName) { // implement me } @Dann( - "{string} empfängt das Attachment {string} von {string} im Raum {string} über Matrix-Protokoll v1.11") - public void empfängtDasAttachmentVonImRaumÜberMatrixProtokollV( - String arg0, String arg1, String arg2, String arg3) { + "{string} findet Healthcare-Service {string} bei Suche nach Namen minus {int}-{int} \\(Anzahl vorne-hinten) Char\\(s) abgeschnitten über die FDV-Schnittstelle") + public void findHealthcareServiceWithSearchParamFromEpaClient( + String actorName, String healthcareServiceName, int begin, int end) { // implement me } @Dann( - "{listOfStrings} hinterlegt auf dem HomeServer sein Dehydrated Device inkl speichern des Schlüsselmaterials") + "{string} findet TI-Messenger-Nutzer {string} bei Suche nach Namen minus {int}-{int} \\(Anzahl vorne-hinten) Char\\(s) abgeschnitten die FDV-Schnittstelle") + public void findPractitionerWithSearchParamFromEpaClient( + String actorName, String healthcareServiceName, int begin, int end) { + // implement me + } + @Dann( - "{listOfStrings} hinterlegen auf dem HomeServer ihre Dehydrated Device inkl speichern des Schlüsselmaterials") - public void postDehydratedDevice(List actorNames) { + "{string} findet {string} im Healthcare-Service {string} über die FDV-Schnittstelle NICHT [Retry 13 - 4]") + public void dontfindHcsEndpintWithSearchParamFromEpaClient( + String actorName, String userEndpoint, String healthcareServiceName) { // implement me } - @Dann("{listOfStrings} haben {string} Dehydrated Device auf dem HomeServer hinterlegt") - @Dann("{listOfStrings} hat {string} Dehydrated Device auf dem HomeServer hinterlegt") - public void getDehydratedDevices(List actorNames, String keineODERein) { + @Dann( + "{string} findet {string} bei Suche in FHIR über die FDV-Schnittstelle NICHT [Retry 13 - 4]") + public void dontFindPractitionerEndpintWithSearchParamFromEpaClient( + String actorName, String userEndpoint, String healthcareServiceName) { // implement me } - @Dann("{listOfStrings} holt sich entschlüsselt sein Dehydrated Device vom HomeServer ab") - @Dann("{listOfStrings} holen sich entschlüsselt ihre Dehydrated Device vom HomeServer ab") - public void getBackDehydratedDevices(List actorNames) { + @Dann( + "{string} setzt die endpointVisibility für seine Practitioner Endpunkt Extension auf {string}") + public void setEndpointVisibilityForPractitioner(String actor, String endpointVisibility) { // implement me } - @Dann("{string} findet {listOfStrings} in FHIR über die FDV-Schnittstelle") - public void findPractitionFromEpaClient(String actor, List actorNames) { + @Dann( + "{string} sieht die endpointVisibility der Practitioner Endpunkt Extension von {string} ist auf dem Wert {string}") + public void getEndpointVisibilityForPractitioner( + String actor, String actorPractitioner, String endpointVisibility) { // implement me } - @Dann("{string} findet {string} im Healthcare-Service {string} über die FDV-Schnittstelle") - public void findHCSFromEpaClient(String actor, List endpointUser, String hcsName) { + @Dann("{string} löscht die endpointVisibility {string} für seine Practitioner Endpunkt Extension") + public void deleteEndpointVisibilityForPractitioner(String actor, String endpointVisibility) { + // implement me + } + + @Dann( + "{string} sieht die endpointVisibility der Practitioner Endpunkt Extension von {string} nicht mehr auf dem Wert {string} [Retry 10 - 3]") + public void getNotEndpointVisibilityForPractitioner( + String actor, String actorPractitioner, String endpointVisibility) { + // implement me + } + + @Dann( + "{string} setzt die endpointVisibility für die Endpunkt Extension von {string} im Healthcare-Service {string} auf {string}") + public void setEndpointVisibilityForHcsEndpiont( + String actor, String hcsEndpoint, String hcsName, String endpointVisibility) { + // implement me + } + + @Dann( + "{string} sieht die endpointVisibility für die Endpunkt Extension von {string} im Healthcare-Service {string} auf dem Wert {string}") + public void getEndpointVisibilityForHcsEndpiont( + String actor, String hcsEndpoint, String hcsName, String endpointVisibility) { + // implement me + } + + @Dann( + "{string} löscht die endpointVisibility {string} für die Endpunkt Extension von {string} im Healthcare-Service {string}") + public void deleteEndpointVisibilityForHcsEndpiont( + String actor, String endpointVisibility, String hcsEndpoint, String hcsName) { + // implement me + } + + @Dann( + "{string} sieht die endpointVisibility für die Endpunkt Extension von {string} im Healthcare-Service {string} nicht mehr auf dem Wert {string} [Retry 10 - 3]") + public void getNotEndpointVisibilityForHcsEndpiont( + String actor, String hcsEndpoint, String hcsName, String endpointVisibility) { + // implement me + } + + @Dann( + "{string} prüft die Raumversion im Raum {string} auf Version {string}") + public void checkRoomVersionRoom( + String actor, String roomName, String version) { + // implement me + } + + @Dann( + "{string} prüft die Raumversion im Chat mit {string} auf Version {string}") + public void checkRoomVersionChat( + String actor, String chatPartner, String version) { + // implement me + } + + @Dann( + "{string} erstellt einen Chat-Raum mit Fallbezug {string}") + public void crateRoomWithCaseReference( + String actor, String roomName) { + // implement me + } + + @Dann( + "{string} prüft, ob die Pflichtparameter in den Room States {listOfStrings} im Raum {string} befüllt sind") + @Then( + "{string} prüft, ob der Pflichtparameter in den Room States {listOfStrings} im Raum {string} befüllt ist") + public void checkParameterFilledForRoomStatesOfRoom( + String actor, List requestedRoomStates, String roomName) { + // implement me + } + + @Dann( + "{string} prüft, ob die Pflichtparameter in den Room States {listOfStrings} im Chat mit {string} befüllt sind") + @Then( + "{string} prüft, ob der Pflichtparameter in den Room States {listOfStrings} im Chat mit {string} befüllt ist") + public void checkParameterFilledForRoomStatesOfChat( + String actor, List requestedRoomStates, String chatPartner) { + // implement me + } + + @Dann( + "{string} prüft, ob die Parameter in den Room States {listOfStrings} im Chat mit {string} leer sind") + @Then( + "{string} prüft, ob der Parameter in den Room States {listOfStrings} im Chat mit {string} leer ist") + public void checkParameterNotExistentForRoomStatesOfChat( + String actor, List requestedRoomStates, String chatPartner) { // implement me } - @Dann("{string} findet Healthcare-Service {string} bei Suche nach Namen minus {int}-{int} \\(Anzahl vorne-hinten) Char\\(s) abgeschnitten über die FDV-Schnittstelle") - public void findHealthcareServiceWithSearchParamFromEpaClient(String actorName, String healthcareServiceName, int begin, int end) { + @Dann( + "{string} prüft, ob die Parameter in den Room States {listOfStrings} im Raum {string} leer sind") + @Then( + "{string} prüft, ob der Parameter in den Room States {listOfStrings} im Raum {string} leer ist") + public void checkParameterNotExistentForRoomStatesOfRoom( + String actor, List requestedRoomStates, String roomName) { // implement me } - @Dann("{string} findet TI-Messenger-Nutzer {string} bei Suche nach Namen minus {int}-{int} \\(Anzahl vorne-hinten) Char\\(s) abgeschnitten die FDV-Schnittstelle") - public void findPractitionerWithSearchParamFromEpaClient(String actorName, String healthcareServiceName, int begin, int end) { + @Dann( + "{string} prüft, ob die Pflichtparameter in den Room States {listOfStrings} im Raum {string} vorhanden sind") + @Then( + "{string} prüft, ob der Pflichtparameter in den Room States {listOfStrings} im Raum {string} vorhanden ist") + public void checkParameterExistentForRoomStatesOfRoom( + String actor, List requestedRoomStates, String roomName) { // implement me } - @Dann("{string} ändert seine letzte Nachricht im Chat mit {string} in {string}") - public void findHCSFromEpaClient(String actor, String chatUser, String message) { + @Dann( + "{string} prüft, ob die Pflichtparameter in den Room States {listOfStrings} im Chat mit {string} vorhanden sind") + @Then( + "{string} prüft, ob der Pflichtparameter in den Room States {listOfStrings} im Chat mit {string} vorhanden ist") + public void checkParameterExistentForRoomStatesOfChat( + String actor, List requestedRoomStates, String chatPartner) { // implement me } - @Dann("{string} ist dem Chat mit {listOfStrings} beigetreten") - public void enterChat(String actor, List chatUser) { + @Then( + "{word} fragt an Schnittstelle {word} die API {string} ab") + public void pingApiOnHomeserver(String actorName, String apiName, String apiUrl) { // implement me } + + @Then( + "{word} fragt an Schnittstelle {word} die API {string} inkl Parameterbefüllung ab") + public void pingApiOnHomeserverIncludingParameter(String actorName, String apiName, String apiUrl) { + // implement me + } + + @Then( + "{string} überprüft, ob die Response der API {string} befüllt ist") + public void pingApiOnHomeserverIncludingParameter(String actorName, String apiUrl) { + // implement me - Werte 200 und 401 (o.ä. sind erlaubt, Ergebniss muss geloggt werden) + } + } diff --git a/src/main/java/de/gematik/tim/test/glue/api/authorization/AddAllowedDomainsTask.java b/src/main/java/de/gematik/tim/test/glue/api/authorization/AddAllowedDomainsTask.java new file mode 100644 index 0000000..77fae6d --- /dev/null +++ b/src/main/java/de/gematik/tim/test/glue/api/authorization/AddAllowedDomainsTask.java @@ -0,0 +1,47 @@ +/* + * + * * Copyright 2024 gematik GmbH + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package de.gematik.tim.test.glue.api.authorization; + +import static de.gematik.tim.test.glue.api.TestdriverApiEndpoint.ADD_ALLOWED_DOMAINS; + +import de.gematik.tim.test.models.AuthorizationListDTO; +import de.gematik.tim.test.models.DomainDTO; +import java.util.List; +import lombok.RequiredArgsConstructor; +import net.serenitybdd.screenplay.Actor; +import net.serenitybdd.screenplay.Task; + +@RequiredArgsConstructor +public class AddAllowedDomainsTask implements Task { + + private final List allowedDomains; + + public static AddAllowedDomainsTask addAllowedDomains(List allowedDomains) { + return new AddAllowedDomainsTask(allowedDomains); + } + + @Override + public void performAs(T actor) { + List domainDTOs = + allowedDomains.stream().map(domain -> new DomainDTO().domain(domain)).toList(); + AuthorizationListDTO allowedList = new AuthorizationListDTO(); + allowedList.domains(domainDTOs); + actor.attemptsTo(ADD_ALLOWED_DOMAINS.request().with(req -> req.body(allowedList))); + } +} diff --git a/src/main/java/de/gematik/tim/test/glue/api/authorization/AddBlockedDomainsTask.java b/src/main/java/de/gematik/tim/test/glue/api/authorization/AddBlockedDomainsTask.java new file mode 100644 index 0000000..54168a4 --- /dev/null +++ b/src/main/java/de/gematik/tim/test/glue/api/authorization/AddBlockedDomainsTask.java @@ -0,0 +1,47 @@ +/* + * + * * Copyright 2024 gematik GmbH + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package de.gematik.tim.test.glue.api.authorization; + +import static de.gematik.tim.test.glue.api.TestdriverApiEndpoint.ADD_BLOCKED_DOMAINS; + +import de.gematik.tim.test.models.AuthorizationListDTO; +import de.gematik.tim.test.models.DomainDTO; +import java.util.List; +import lombok.RequiredArgsConstructor; +import net.serenitybdd.screenplay.Actor; +import net.serenitybdd.screenplay.Task; + +@RequiredArgsConstructor +public class AddBlockedDomainsTask implements Task { + + private final List blockedDomains; + + public static AddBlockedDomainsTask addBlockedDomains(List blockedDomains) { + return new AddBlockedDomainsTask(blockedDomains); + } + + @Override + public void performAs(T actor) { + List domainDTOs = + blockedDomains.stream().map(domain -> new DomainDTO().domain(domain)).toList(); + AuthorizationListDTO blockedList = new AuthorizationListDTO(); + blockedList.domains(domainDTOs); + actor.attemptsTo(ADD_BLOCKED_DOMAINS.request().with(req -> req.body(blockedList))); + } +} diff --git a/src/main/java/de/gematik/tim/test/glue/api/authorization/AuthorizationGlue.java b/src/main/java/de/gematik/tim/test/glue/api/authorization/AuthorizationGlue.java index 2432cf2..1588e51 100644 --- a/src/main/java/de/gematik/tim/test/glue/api/authorization/AuthorizationGlue.java +++ b/src/main/java/de/gematik/tim/test/glue/api/authorization/AuthorizationGlue.java @@ -18,9 +18,13 @@ import static de.gematik.tim.test.glue.api.ActorMemoryKeys.MX_ID; import static de.gematik.tim.test.glue.api.GeneralStepsGlue.checkResponseCode; +import static de.gematik.tim.test.glue.api.authorization.AddAllowedDomainsTask.addAllowedDomains; import static de.gematik.tim.test.glue.api.authorization.AddAllowedUsersTask.addAllowedUsers; +import static de.gematik.tim.test.glue.api.authorization.AddBlockedDomainsTask.addBlockedDomains; import static de.gematik.tim.test.glue.api.authorization.AddBlockedUsersTask.addBlockedUsers; +import static de.gematik.tim.test.glue.api.authorization.DeleteAllowedDomainsTask.deleteAllowedDomains; import static de.gematik.tim.test.glue.api.authorization.DeleteAllowedUsersTask.deleteAllowedUsers; +import static de.gematik.tim.test.glue.api.authorization.DeleteBlockedDomainsTask.deleteBlockedDomains; import static de.gematik.tim.test.glue.api.authorization.DeleteBlockedUsersTask.deleteBlockedUsers; import static de.gematik.tim.test.glue.api.authorization.GetAuthorizationModeQuestion.getAuthorizationMode; import static de.gematik.tim.test.glue.api.authorization.SetAuthorizationModeTask.setAuthorizationMode; @@ -115,4 +119,58 @@ public void deleteUserFromAllowList(String actorName, List allowedUserNa actor.attemptsTo(deleteAllowedUsers(allowedUsersMxids)); checkResponseCode(actorName, NO_CONTENT.value()); } + + @Then("{string} puts the domain of {listOfStrings} on the block list") + @Dann("{string} hinterlegt die Domain von {listOfStrings} in der Blockliste") + public void putDomainInBlockList(String actorName, List blockedUsers) { + Actor actor = theActorCalled(actorName); + List blockedDomains = getDomainsFromUsers(blockedUsers); + actor.attemptsTo(addBlockedDomains(blockedDomains)); + checkResponseCode(actorName, OK.value()); + } + + @Then("{string} removes the domain of {listOfStrings} from the block list") + @Dann("{string} entfernt die Domain von {listOfStrings} in der Blockliste") + public void deleteDomainInBlockList(String actorName, List blockedUsers) { + Actor actor = theActorCalled(actorName); + List blockedDomains = getDomainsFromUsers(blockedUsers); + actor.attemptsTo(deleteBlockedDomains(blockedDomains)); + checkResponseCode(actorName, NO_CONTENT.value()); + } + + @Then("{string} puts the domain of {listOfStrings} on the allow list") + @Dann("{string} hinterlegt die Domain von {listOfStrings} in der Allowliste") + public void putDomainInAllowList(String actorName, List allowedUsers) { + Actor actor = theActorCalled(actorName); + List allowedDomains = getDomainsFromUsers(allowedUsers); + actor.attemptsTo(addAllowedDomains(allowedDomains)); + checkResponseCode(actorName, OK.value()); + } + + @Then("{string} removes the domain of {listOfStrings} from the allow list") + @Dann("{string} entfernt die Domain von {listOfStrings} in der Allowliste") + public void deleteDomainInAllowList(String actorName, List allowedUsers) { + Actor actor = theActorCalled(actorName); + List allowedDomains = getDomainsFromUsers(allowedUsers); + actor.attemptsTo(deleteAllowedDomains(allowedDomains)); + checkResponseCode(actorName, NO_CONTENT.value()); + } + + private List getDomainsFromUsers(List allowedUsers) { + List domains = new ArrayList<>(); + for (String allowedUser : allowedUsers) { + Actor allowedActor = theActorCalled(allowedUser); + String mxId = allowedActor.recall(MX_ID); + String domain = extractDomainFromMxId(mxId); + domains.add(domain); + } + return domains; + } + + private String extractDomainFromMxId(String mxId) { + if (mxId == null || !mxId.contains(":")) { + throw new IllegalArgumentException(mxId + " is not a valid MxId"); + } + return mxId.split(":")[1]; + } } diff --git a/src/main/java/de/gematik/tim/test/glue/api/authorization/DeleteAllowedDomainsTask.java b/src/main/java/de/gematik/tim/test/glue/api/authorization/DeleteAllowedDomainsTask.java new file mode 100644 index 0000000..3172909 --- /dev/null +++ b/src/main/java/de/gematik/tim/test/glue/api/authorization/DeleteAllowedDomainsTask.java @@ -0,0 +1,47 @@ +/* + * + * * Copyright 2024 gematik GmbH + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package de.gematik.tim.test.glue.api.authorization; + +import static de.gematik.tim.test.glue.api.TestdriverApiEndpoint.DELETE_ALLOWED_DOMAINS; + +import de.gematik.tim.test.models.AuthorizationListDTO; +import de.gematik.tim.test.models.DomainDTO; +import java.util.List; +import lombok.RequiredArgsConstructor; +import net.serenitybdd.screenplay.Actor; +import net.serenitybdd.screenplay.Task; + +@RequiredArgsConstructor +public class DeleteAllowedDomainsTask implements Task { + + private final List allowedDomains; + + public static DeleteAllowedDomainsTask deleteAllowedDomains(List allowedDomains) { + return new DeleteAllowedDomainsTask(allowedDomains); + } + + @Override + public void performAs(T actor) { + List domainDTOs = + allowedDomains.stream().map(domain -> new DomainDTO().domain(domain)).toList(); + AuthorizationListDTO allowedList = new AuthorizationListDTO(); + allowedList.domains(domainDTOs); + actor.attemptsTo(DELETE_ALLOWED_DOMAINS.request().with(req -> req.body(allowedList))); + } +} diff --git a/src/main/java/de/gematik/tim/test/glue/api/authorization/DeleteBlockedDomainsTask.java b/src/main/java/de/gematik/tim/test/glue/api/authorization/DeleteBlockedDomainsTask.java new file mode 100644 index 0000000..f49a1de --- /dev/null +++ b/src/main/java/de/gematik/tim/test/glue/api/authorization/DeleteBlockedDomainsTask.java @@ -0,0 +1,47 @@ +/* + * + * * Copyright 2024 gematik GmbH + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package de.gematik.tim.test.glue.api.authorization; + +import static de.gematik.tim.test.glue.api.TestdriverApiEndpoint.DELETE_BLOCKED_DOMAINS; + +import de.gematik.tim.test.models.AuthorizationListDTO; +import de.gematik.tim.test.models.DomainDTO; +import java.util.List; +import lombok.RequiredArgsConstructor; +import net.serenitybdd.screenplay.Actor; +import net.serenitybdd.screenplay.Task; + +@RequiredArgsConstructor +public class DeleteBlockedDomainsTask implements Task { + + private final List blockedDomains; + + public static DeleteBlockedDomainsTask deleteBlockedDomains(List blockedDomains) { + return new DeleteBlockedDomainsTask(blockedDomains); + } + + @Override + public void performAs(T actor) { + List domainDTOs = + blockedDomains.stream().map(domain -> new DomainDTO().domain(domain)).toList(); + AuthorizationListDTO blockedList = new AuthorizationListDTO(); + blockedList.domains(domainDTOs); + actor.attemptsTo(DELETE_BLOCKED_DOMAINS.request().with(req -> req.body(blockedList))); + } +} diff --git a/src/main/java/de/gematik/tim/test/glue/api/fhir/practitioner/FhirAdministrationGlue.java b/src/main/java/de/gematik/tim/test/glue/api/fhir/practitioner/FhirAdministrationGlue.java index d5e434e..3786d28 100644 --- a/src/main/java/de/gematik/tim/test/glue/api/fhir/practitioner/FhirAdministrationGlue.java +++ b/src/main/java/de/gematik/tim/test/glue/api/fhir/practitioner/FhirAdministrationGlue.java @@ -55,7 +55,7 @@ public void addToFhir(List actorNames) { actorName -> { Actor actor = theActorCalled(actorName); actor.attemptsTo(authenticateOnFhirVzd()); - checkResponseCode(); + checkResponseCode(actorName, OK.value()); actor.attemptsTo(setMxid()); checkResponseCode(actorName, CREATED.value()); }); diff --git a/src/main/java/de/gematik/tim/test/glue/api/media/DownloadAuthenticatedMediaQuestion.java b/src/main/java/de/gematik/tim/test/glue/api/media/DownloadAuthenticatedMediaQuestion.java new file mode 100644 index 0000000..b8d520b --- /dev/null +++ b/src/main/java/de/gematik/tim/test/glue/api/media/DownloadAuthenticatedMediaQuestion.java @@ -0,0 +1,49 @@ +/* + * Copyright 2023 gematik GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.gematik.tim.test.glue.api.media; + +import static de.gematik.tim.test.glue.api.ActorMemoryKeys.MEDIA_ID; +import static de.gematik.tim.test.glue.api.TestdriverApiEndpoint.DOWNLOAD_AUTHENTICATED_MEDIA; +import static de.gematik.tim.test.glue.api.TestdriverApiPath.MEDIA_ID_VARIABLE; +import static net.serenitybdd.rest.SerenityRest.lastResponse; + +import net.serenitybdd.screenplay.Actor; +import net.serenitybdd.screenplay.Question; + +public class DownloadAuthenticatedMediaQuestion implements Question { + + private String fileId; + + public static DownloadAuthenticatedMediaQuestion downloadAuthenticatedMedia() { + return new DownloadAuthenticatedMediaQuestion(); + } + + public DownloadAuthenticatedMediaQuestion withFileId(String fileId) { + this.fileId = fileId; + return this; + } + + @Override + public byte[] answeredBy(Actor actor) { + String mediaId = fileId == null ? actor.recall(MEDIA_ID) : this.fileId; + actor.attemptsTo( + DOWNLOAD_AUTHENTICATED_MEDIA + .request() + .with(query -> query.pathParam(MEDIA_ID_VARIABLE, mediaId))); + return lastResponse().body().asByteArray(); + } +} diff --git a/src/main/java/de/gematik/tim/test/glue/api/media/MediaGlue.java b/src/main/java/de/gematik/tim/test/glue/api/media/MediaGlue.java index a32578b..9a35208 100644 --- a/src/main/java/de/gematik/tim/test/glue/api/media/MediaGlue.java +++ b/src/main/java/de/gematik/tim/test/glue/api/media/MediaGlue.java @@ -19,6 +19,7 @@ import static de.gematik.tim.test.glue.api.ActorMemoryKeys.MEDIA_ID; import static de.gematik.tim.test.glue.api.ActorMemoryKeys.MX_ID; import static de.gematik.tim.test.glue.api.GeneralStepsGlue.checkResponseCode; +import static de.gematik.tim.test.glue.api.media.DownloadAuthenticatedMediaQuestion.downloadAuthenticatedMedia; import static de.gematik.tim.test.glue.api.media.DownloadMediaQuestion.downloadMedia; import static de.gematik.tim.test.glue.api.media.UploadMediaTask.uploadMedia; import static de.gematik.tim.test.glue.api.message.GetRoomMessageQuestion.messageFromSenderWithTextInActiveRoom; @@ -31,7 +32,6 @@ import static org.springframework.http.HttpStatus.CREATED; import static org.springframework.http.HttpStatus.OK; - import de.gematik.tim.test.glue.api.exceptions.TestRunException; import de.gematik.tim.test.glue.api.room.UseRoomAbility; import de.gematik.tim.test.models.MessageDTO; @@ -61,12 +61,11 @@ public void sendsAttachmentToRoom(String actorName, String fileName, String room String msgType; if (fileName.endsWith(".jpg") || fileName.endsWith(".png")) { msgType = "m.image"; - } - else if (fileName.endsWith(".txt")) { + } else if (fileName.endsWith(".txt")) { msgType = "m.text"; - } - else{ - throw new NotImplementedException("Unknown file type. Add a new messageType in the glue step to support this file."); + } else { + throw new NotImplementedException( + "Unknown file type. Add a new messageType in the glue step to support this file."); } Actor actor = theActorCalled(actorName); actor.abilityTo(UseRoomAbility.class).setActive(roomName); @@ -89,28 +88,55 @@ private void uploadsAMediaFile(String actorName, String media) { checkResponseCode(actorName, CREATED.value()); } - @SneakyThrows @Then("{string} receives the attachment {string} from {string} in the room {string}") @Dann("{string} empfängt das Attachment {string} von {string} im Raum {string}") public void receiveAttachmentInRoom( - String actorName, String fileName, String userName, String roomName) { - Actor actor = theActorCalled(actorName); + String receiverName, String fileName, String senderName, String roomName) { + Actor actor = theActorCalled(receiverName); + actor.abilityTo(UseRoomAbility.class).setActive(roomName); + MessageDTO message = getMediaMessage(senderName, receiverName, fileName); + byte[] receivedMedia = actor.asksFor(downloadMedia().withFileId(message.getFileId())); + + checkResponseCode(receiverName, OK.value()); + checkMediaIntegrity(fileName, receivedMedia, message); + checkRoomMembershipState(actor, roomName); + } + + @Then( + "{string} receives an attachment {string} from {string} in the room {string} using matrix protocol v1.11") + @Dann( + "{string} empfängt das Attachment {string} von {string} im Raum {string} über Matrix-Protokoll v1.11") + public void receiveAuthenticatedAttachmentInRoom( + String receiverName, String fileName, String senderName, String roomName) { + Actor actor = theActorCalled(receiverName); actor.abilityTo(UseRoomAbility.class).setActive(roomName); - String senderMxId = theActorCalled(userName).recall(MX_ID); + MessageDTO message = getMediaMessage(senderName, receiverName, fileName); + byte[] receivedMedia = + actor.asksFor(downloadAuthenticatedMedia().withFileId(message.getFileId())); + + checkResponseCode(receiverName, OK.value()); + checkMediaIntegrity(fileName, receivedMedia, message); + checkRoomMembershipState(actor, roomName); + } + + private MessageDTO getMediaMessage(String senderName, String receiverName, String fileName) { + Actor actor = theActorCalled(receiverName); + String senderMxId = theActorCalled(senderName).recall(MX_ID); Optional message = actor.asksFor(messageFromSenderWithTextInActiveRoom(fileName, senderMxId)); - if (message.isEmpty()) { throw new TestRunException( format("Could not find message %s from sender %s", fileName, senderMxId)); } - byte[] receivedMedia = actor.asksFor(downloadMedia().withFileId(message.get().getFileId())); + return message.get(); + } + @SneakyThrows + private void checkMediaIntegrity(String fileName, byte[] receivedMedia, MessageDTO message) { Path path = Path.of(RESOURCES_PATH + fileName); try (FileInputStream fis = new FileInputStream(path.toFile())) { assertThat(receivedMedia).isEqualTo(fis.readAllBytes()); } - assertThat(message.get().getBody()).isEqualTo(getCreatedMessage(fileName).getBody()); - checkRoomMembershipState(actor, roomName); + assertThat(message.getBody()).isEqualTo(getCreatedMessage(fileName).getBody()); } } diff --git a/src/main/java/de/gematik/tim/test/glue/api/message/MessageControllerGlue.java b/src/main/java/de/gematik/tim/test/glue/api/message/MessageControllerGlue.java index 87d5012..413b214 100644 --- a/src/main/java/de/gematik/tim/test/glue/api/message/MessageControllerGlue.java +++ b/src/main/java/de/gematik/tim/test/glue/api/message/MessageControllerGlue.java @@ -259,4 +259,11 @@ public void editsHerLastSentMessageTo(String actorName, String roomName, String actor.attemptsTo(editMessage().withMessage(messageText).withMessageId(message.getMessageId())); checkResponseCode(actorName, OK.value()); } + + @Then("{string} edits her last sent message in chat with {string} to {string}") + @Dann("{string} ändert seine letzte Nachricht im Chat mit {string} in {string}") + public void editsLastSentMessageInChat(String actorName, String chatUser, String messageText) { + editsHerLastSentMessageTo( + actorName, DIRECT_CHAT_NAME + theActorCalled(chatUser).recall(MX_ID), messageText); + } } diff --git a/src/main/java/de/gematik/tim/test/glue/api/room/RoomControllerGlue.java b/src/main/java/de/gematik/tim/test/glue/api/room/RoomControllerGlue.java index ab30cc4..0e0ea37 100644 --- a/src/main/java/de/gematik/tim/test/glue/api/room/RoomControllerGlue.java +++ b/src/main/java/de/gematik/tim/test/glue/api/room/RoomControllerGlue.java @@ -19,6 +19,7 @@ import static com.jayway.jsonpath.JsonPath.parse; import static de.gematik.tim.test.glue.api.ActorMemoryKeys.DIRECT_CHAT_NAME; import static de.gematik.tim.test.glue.api.ActorMemoryKeys.MX_ID; +import static de.gematik.tim.test.glue.api.ActorMemoryKeys.OWN_ROOM_MEMBERSHIP_STATUS_POSTFIX; import static de.gematik.tim.test.glue.api.GeneralStepsGlue.checkResponseCode; import static de.gematik.tim.test.glue.api.fhir.organisation.FhirOrgAdminGlue.findsAddressInHealthcareService; import static de.gematik.tim.test.glue.api.room.UseRoomAbility.addRoomToActor; @@ -33,6 +34,7 @@ import static de.gematik.tim.test.glue.api.room.tasks.LeaveRoomTask.leaveRoom; import static de.gematik.tim.test.glue.api.utils.GlueUtils.checkRoomMembershipState; import static de.gematik.tim.test.glue.api.utils.GlueUtils.checkRoomVersion; +import static de.gematik.tim.test.glue.api.utils.RequestResponseUtils.parseResponse; import static de.gematik.tim.test.glue.api.utils.TestcasePropertiesManager.getAllActiveActorsByMxIds; import static de.gematik.tim.test.glue.api.utils.TestcasePropertiesManager.getRoomByInternalName; import static de.gematik.tim.test.models.RoomMembershipStateDTO.INVITE; @@ -58,6 +60,7 @@ import io.cucumber.java.en.And; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Set; @@ -133,7 +136,6 @@ private void inviteUserToChatWith( String roomId = invitingActor.abilityTo(UseRoomAbility.class).getRoomIdByName(DIRECT_CHAT_NAME + thirdMxid); - invitingActor.attemptsTo(invite(List.of(invitedMxid)).toRoom(roomId)); } @@ -188,6 +190,20 @@ public void acceptsTheInvitationToRoom( RoomDTO roomWithLimitedMemberView = invitedActor.asksFor(ownRoom().withMemberHasStatus(invitedActor.recall(MX_ID), INVITE)); invitedActor.attemptsTo(joinRoom().withRoomId(roomWithLimitedMemberView.getRoomId())); + RoomDTO roomUpdated = parseResponse(RoomDTO.class); + List roomMembers = roomUpdated.getMembers(); + Optional optionalRoomMemberDTO = + roomMembers.stream() + .filter(member -> invitedActor.recall(MX_ID).equals(member.getMxid())) + .findFirst(); + if (optionalRoomMemberDTO.isPresent()) { + RoomMemberDTO roomMember = optionalRoomMemberDTO.get(); + RoomMembershipStateDTO status = + invitedActor.recall(roomUpdated.getRoomId() + OWN_ROOM_MEMBERSHIP_STATUS_POSTFIX); + if (!roomMember.getMembershipState().equals(status)) { + throw new TestRunException(format("%s join room task failed", actorName)); + } + } checkResponseCode(actorName, OK.value()); checkRoomMembershipState(); } @@ -359,8 +375,22 @@ public void userInRoom(String actorName, String roomName) { Actor actor = theActorCalled(actorName); RoomDTO room = actor.asksFor(ownRoom().withName(roomName).withMemberHasStatus(actor.recall(MX_ID), JOIN)); + assertThat(room).as(format("Actor %s has not joined room %s", actorName, roomName)).isNotNull(); + checkRoomMembershipState(room); + } + + @Then("{string} joined the chat with {listOfStrings}") + @Dann("{string} ist dem Chat mit {listOfStrings} beigetreten") + public void userInDirectChat(String actorName, List chatMembers) { + Actor actor = theActorCalled(actorName); + List chatMemberMxIds = new ArrayList<>(); + for (String chatMember : chatMembers) { + chatMemberMxIds.add(theActorCalled(chatMember).recall(MX_ID)); + } + chatMemberMxIds.add(actor.recall(MX_ID)); + RoomDTO room = actor.asksFor(ownRoom().withMembers(chatMemberMxIds)); assertThat(room) - .as(format("Actor %s have not joined room %s", actorName, roomName)) + .as(format("Actor %s has not joined room with %s", actorName, chatMembers)) .isNotNull(); checkRoomMembershipState(room); } diff --git a/src/main/java/de/gematik/tim/test/glue/api/room/UseRoomAbility.java b/src/main/java/de/gematik/tim/test/glue/api/room/UseRoomAbility.java index 491ec8a..85409e5 100644 --- a/src/main/java/de/gematik/tim/test/glue/api/room/UseRoomAbility.java +++ b/src/main/java/de/gematik/tim/test/glue/api/room/UseRoomAbility.java @@ -95,7 +95,7 @@ public static void updateAvailableRooms(List rooms, Actor actor) { } public String getRoomIdByName(String roomName) { - return getTarget(roomName).getName(); + return getTarget(roomName).getRoomId(); } @Override diff --git a/src/main/java/de/gematik/tim/test/glue/api/room/tasks/InviteToRoomTask.java b/src/main/java/de/gematik/tim/test/glue/api/room/tasks/InviteToRoomTask.java index 45fe703..2586092 100644 --- a/src/main/java/de/gematik/tim/test/glue/api/room/tasks/InviteToRoomTask.java +++ b/src/main/java/de/gematik/tim/test/glue/api/room/tasks/InviteToRoomTask.java @@ -64,7 +64,8 @@ public void performAs(T actor) { if (canBeInvited) { getAllActiveActorsByMxIds(invitees.stream().map(MxIdDTO::getMxid).toList(), shouldFindMxid) - .forEach(a -> a.remember(roomId + OWN_ROOM_MEMBERSHIP_STATUS_POSTFIX, INVITE)); + .forEach( + invitee -> invitee.remember(roomId + OWN_ROOM_MEMBERSHIP_STATUS_POSTFIX, INVITE)); sendRawDataEvent(actor.recall(MX_ID)); } } diff --git a/src/main/java/de/gematik/tim/test/glue/api/utils/GlueUtils.java b/src/main/java/de/gematik/tim/test/glue/api/utils/GlueUtils.java index 051404f..c66eb95 100644 --- a/src/main/java/de/gematik/tim/test/glue/api/utils/GlueUtils.java +++ b/src/main/java/de/gematik/tim/test/glue/api/utils/GlueUtils.java @@ -383,6 +383,7 @@ private static void checkIfAllMembersAreCorrect(RoomDTO room) { member.getMxid(), room.getRoomId()))); RoomMembershipStateDTO status = actorForMember.recall(room.getRoomId() + OWN_ROOM_MEMBERSHIP_STATUS_POSTFIX); + if (!member.getMembershipState().equals(status)) { handleRoomStateInconsistency( format( diff --git a/src/main/resources/api/TiMessengerTestTreiber.yaml b/src/main/resources/api/TiMessengerTestTreiber.yaml index 7f76d47..1f3ca59 100644 --- a/src/main/resources/api/TiMessengerTestTreiber.yaml +++ b/src/main/resources/api/TiMessengerTestTreiber.yaml @@ -1567,7 +1567,7 @@ paths: - TI-M_1.1.x - TI-M_Pro - TI-M_ePA - summary: "Uploads a file and returns its file-id" + summary: "Uploads a file and returns its fileId" operationId: postMediaFile parameters: - in: header @@ -1600,8 +1600,6 @@ paths: tags: - media - TI-M_1.1.x - - TI-M_Pro - - TI-M_ePA summary: "Returns a previously uploaded file with given id" operationId: getMediaFile responses: @@ -1617,19 +1615,34 @@ paths: default: $ref: "#/components/responses/DefaultResponse" - delete: + /devices/{deviceId}/media/authenticated/{fileId}: + parameters: + - $ref: "#/components/parameters/deviceId" + - $ref: "#/components/parameters/transactionIdHeader" + - $ref: "#/components/parameters/fileId" + get: tags: - media - - TI-M_1.1.x - TI-M_Pro - TI-M_ePA - summary: "Deletes a previously uploaded file with given id" - operationId: deleteMediaFile + summary: "Returns a previously uploaded file with authentication" + description: + "Since Matrix version 1.11 the download of media files is authenticated. + This endpoint is used to test the new authenticated download, + where fileId is the id received during upload." + operationId: getAuthenticatedMediaFile responses: - "204": - description: "Media deleted" + "200": + description: "Retrieved the media file" + content: + application/octet-stream: + schema: + type: string + format: binary "404": $ref: "#/components/responses/NotFound" + default: + $ref: "#/components/responses/DefaultResponse" /devices/{deviceId}/authorizationMode: parameters: @@ -2021,7 +2034,7 @@ paths: - TI-M_Pro - TI-M_ePA summary: "Deletes the domain from the list of users and domains not allowed to contact the client" - operationId: deleteBlockedDomain + operationId: deleteBlockedUserDomain responses: "204": description: "Blocked user domain deleted"