scoped programmatic i18n-keys (#190)
Co-authored-by: Michael Hoennig <michael@hoennig.de> Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/190 Reviewed-by: Timotheus Pokorra <timotheus.pokorra@hostsharing.net>
This commit is contained in:
+2
-2
@@ -69,7 +69,7 @@ class CasAuthenticationFilterIntegrationTest {
|
||||
|
||||
// when
|
||||
final var result = restTemplate.exchange(
|
||||
"http://localhost:" + this.serverPort + "/api/ping",
|
||||
"http://localhost:" + this.serverPort + "/api/pong",
|
||||
HttpMethod.GET,
|
||||
new HttpEntity<>(null, headers(entry("Authorization", "ST-valid"))),
|
||||
String.class
|
||||
@@ -77,7 +77,7 @@ class CasAuthenticationFilterIntegrationTest {
|
||||
|
||||
// then
|
||||
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(result.getBody()).startsWith("pong " + username);
|
||||
assertThat(result.getBody()).startsWith("ponged " + username);
|
||||
// HOWTO assert log messages
|
||||
assertThat(capturedOutput.getOut()).containsPattern(
|
||||
LogbackLogPattern.of(LogLevel.DEBUG, RealCasAuthenticator.class, "CAS-user: " + username));
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package net.hostsharing.hsadminng.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import lombok.val;
|
||||
|
||||
@SpringBootTest(classes = {
|
||||
MessagesResourceConfig.class,
|
||||
MessageTranslator.class
|
||||
})
|
||||
@ActiveProfiles("test")
|
||||
@Tag("generalIntegrationTest")
|
||||
class MessageTranslatorIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext webApplicationContext;
|
||||
|
||||
@MockitoBean
|
||||
private Context contextMock; // avoiding dependency issues
|
||||
|
||||
@AllArgsConstructor
|
||||
enum TestCases {
|
||||
ENGLISH_KNOWN(Locale.ENGLISH, "test.ponged-{0}--in-your-language",
|
||||
"ponged testUser - in English"),
|
||||
ENGLISH_UNKNOWN(Locale.ENGLISH, "test.ponged-{0}--unknown-key",
|
||||
"【⍰ponged testUser - unknown key⍰】"),
|
||||
ENGLISH_US(Locale.of("en", "US"), "test.ponged-{0}--in-your-language",
|
||||
"ponged testUser - in English"),
|
||||
ENGLISH_UK(Locale.of("en", "UK"), "test.ponged-{0}--in-your-language",
|
||||
"ponged testUser - in English"),
|
||||
GERMAN_KNOWN(Locale.GERMAN, "test.ponged-{0}--in-your-language",
|
||||
"ponged testUser - auf Deutsch"),
|
||||
FRENCH_UNKNOWN_BUT_ENGLISH_KNOWN(Locale.FRENCH, "test.ponged-{0}--in-your-language",
|
||||
"【⍰ponged testUser - in English⍰】"),
|
||||
FRENCH_UNKNOWN_AND_ENGLISH_UNKNOWN(Locale.FRENCH, "test.ponged-{0}--unknown-key",
|
||||
"【⍰ponged testUser - unknown key⍰】"),
|
||||
UNKNOWN_LOCALE_AND_ENGLISH_KNOWN(Locale.TRADITIONAL_CHINESE,
|
||||
"test.ponged-{0}--in-your-language", "【⍰ponged testUser - in English⍰】"),
|
||||
UNKNOWN_LOCALE_AND_ENGLISH_UNKNOWN(Locale.TRADITIONAL_CHINESE, "test.ponged-{0}--unknown-key",
|
||||
"【⍰ponged testUser - unknown key⍰】");
|
||||
final Locale locale;
|
||||
final String messageKey;
|
||||
final String expectedTranslation;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(TestCases.class)
|
||||
void shouldHandleDifferentLocalesAppropriately(final TestCases testCase) {
|
||||
// given
|
||||
val messageTranslator = webApplicationContext.getBean(MessageTranslator.class);
|
||||
|
||||
// when
|
||||
val result = messageTranslator.translateTo(testCase.locale, testCase.messageKey, "testUser");
|
||||
|
||||
// then
|
||||
assertThat(result).isEqualTo(testCase.expectedTranslation);
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -67,14 +67,14 @@ class WebSecurityConfigIntegrationTest {
|
||||
|
||||
// http request
|
||||
final var result = restTemplate.exchange(
|
||||
"http://localhost:" + this.serverPort + "/api/ping",
|
||||
"http://localhost:" + this.serverPort + "/api/pong",
|
||||
HttpMethod.GET,
|
||||
httpHeaders(entry("Authorization", "Bearer ST-fake-cas-ticket")),
|
||||
String.class
|
||||
);
|
||||
|
||||
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(result.getBody()).startsWith("pong fake-user-name");
|
||||
assertThat(result.getBody()).startsWith("ponged fake-user-name");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -85,18 +85,18 @@ class WebSecurityConfigIntegrationTest {
|
||||
|
||||
// http request
|
||||
final var result = restTemplate.exchange(
|
||||
"http://localhost:" + this.serverPort + "/api/ping",
|
||||
"http://localhost:" + this.serverPort + "/api/pong",
|
||||
HttpMethod.GET,
|
||||
httpHeaders(entry("Authorization", "Bearer TGT-fake-cas-ticket")),
|
||||
String.class
|
||||
);
|
||||
|
||||
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(result.getBody()).startsWith("pong fake-user-name");
|
||||
assertThat(result.getBody()).startsWith("ponged fake-user-name");
|
||||
}
|
||||
|
||||
@Test
|
||||
void accessToApiWithInvalidTicketGrantingTicketShouldBePermitted() {
|
||||
void accessToOpenApiWithInvalidTicketGrantingTicketShouldBePermitted() {
|
||||
// given
|
||||
givenCasServiceTicketForTicketGrantingTicket("TGT-fake-cas-ticket", "ST-fake-cas-ticket");
|
||||
givenCasTicketValidationResponse("ST-fake-cas-ticket", "fake-user-name");
|
||||
@@ -113,14 +113,14 @@ class WebSecurityConfigIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void accessToPingApiWithoutTokenShouldBePermitted() {
|
||||
void accessToOpenApiWithoutTokenShouldBePermitted() {
|
||||
final var result = this.restTemplate.getForEntity(
|
||||
"http://localhost:" + this.serverPort + "/api/ping", String.class);
|
||||
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
void accessToPongApiWithValidTokenShouldBePermitted() {
|
||||
void accessToProtectedApiWithValidTokenShouldBePermitted() {
|
||||
// given
|
||||
givenCasTicketValidationResponse("ST-fake-cas-ticket", "fake-user-name");
|
||||
|
||||
@@ -137,7 +137,7 @@ class WebSecurityConfigIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void accessToPongApiWithInvalidTokenShouldBeDenied() {
|
||||
void accessToProtectedApiWithInvalidTokenShouldBeDenied() {
|
||||
// given
|
||||
givenCasTicketValidationResponse("ST-fake-cas-ticket", "fake-user-name");
|
||||
|
||||
|
||||
+1
-1
@@ -190,7 +190,7 @@ class HsCredentialsControllerRestTest {
|
||||
given(rbacPersonRepo.findByUuid(personUuid)).willReturn(Optional.of(
|
||||
HsOfficePersonRbacEntity.builder().uuid(personUuid).personType(NATURAL_PERSON).build()
|
||||
));
|
||||
given(rbacPersonRepo.findPersonsrepresentedByPersonWithUuid(personUuid)).willReturn(List.of(
|
||||
given(rbacPersonRepo.findPersonsRepresentedByPersonWithUuid(personUuid)).willReturn(List.of(
|
||||
// some persons, but not the one from the login-user itself
|
||||
HsOfficePersonRbacEntity.builder().uuid(UUID.randomUUID()).personType(NATURAL_PERSON).build(),
|
||||
HsOfficePersonRbacEntity.builder().uuid(UUID.randomUUID()).personType(LEGAL_PERSON).build()
|
||||
|
||||
+2
-1
@@ -4,6 +4,7 @@ import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import net.hostsharing.hsadminng.HsadminNgApplication;
|
||||
import net.hostsharing.hsadminng.config.MessageTranslator;
|
||||
import net.hostsharing.hsadminng.config.MessagesResourceConfig;
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipRepository;
|
||||
import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup;
|
||||
@@ -36,7 +37,7 @@ import static org.hamcrest.Matchers.startsWith;
|
||||
@SpringBootTest(
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = { HsadminNgApplication.class, DisableSecurityConfig.class, JpaAttempt.class,
|
||||
MessageTranslator.class}
|
||||
MessagesResourceConfig.class, MessageTranslator.class}
|
||||
)
|
||||
@ActiveProfiles("test")
|
||||
@Transactional
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@ package net.hostsharing.hsadminng.hs.office.membership;
|
||||
|
||||
import io.hypersistence.utils.hibernate.type.range.Range;
|
||||
import net.hostsharing.hsadminng.config.MessageTranslator;
|
||||
import net.hostsharing.hsadminng.config.MessagesResourceConfig;
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import net.hostsharing.hsadminng.hs.office.coopassets.HsOfficeCoopAssetsTransactionRepository;
|
||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRbacEntity;
|
||||
@@ -41,7 +42,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@WebMvcTest(HsOfficeMembershipController.class)
|
||||
@Import({StrictMapper.class, DisableSecurityConfig.class, MessageTranslator.class})
|
||||
@Import({ StrictMapper.class, DisableSecurityConfig.class, MessagesResourceConfig.class, MessageTranslator.class})
|
||||
@ActiveProfiles("test")
|
||||
public class HsOfficeMembershipControllerRestTest {
|
||||
|
||||
|
||||
+2
-2
@@ -259,14 +259,14 @@ class HsOfficePersonRbacRepositoryIntegrationTest extends ContextBasedTestWithCl
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findPersonsrepresentedByPersonWithUuid() {
|
||||
public void findPersonsRepresentedByPersonWithUuid() {
|
||||
|
||||
// given
|
||||
context("superuser-alex@hostsharing.net");
|
||||
final var personUuid = personRbacRepo.findPersonByOptionalNameLike("Fouler").getFirst().getUuid();
|
||||
|
||||
// when
|
||||
@SuppressWarnings("unchecked") final List<HsOfficePersonRbacEntity> representedPersons = personRbacRepo.findPersonsrepresentedByPersonWithUuid(personUuid);
|
||||
@SuppressWarnings("unchecked") final List<HsOfficePersonRbacEntity> representedPersons = personRbacRepo.findPersonsRepresentedByPersonWithUuid(personUuid);
|
||||
|
||||
// then
|
||||
assertThat(representedPersons).map(Object::toString).containsExactlyInAnyOrder(
|
||||
|
||||
@@ -6,6 +6,7 @@ import net.hostsharing.hsadminng.config.DisableSecurityConfig;
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -40,36 +41,52 @@ class PingControllerAcceptanceTest {
|
||||
@Autowired
|
||||
Context contextMock;
|
||||
|
||||
enum PingTranslationTestCase {
|
||||
EN(Locale.ENGLISH, "pong superuser-alex@hostsharing.net - in English"),
|
||||
DE(Locale.GERMAN, "pong superuser-alex@hostsharing.net - auf Deutsch"),
|
||||
FR(Locale.FRENCH, "pong superuser-alex@hostsharing.net - in English [fr translation missing]");
|
||||
enum PongTranslationTestCase {
|
||||
EN(Locale.ENGLISH, "ponged superuser-alex@hostsharing.net - in English"),
|
||||
DE(Locale.GERMAN, "ponged superuser-alex@hostsharing.net - auf Deutsch");
|
||||
|
||||
Locale givenLocale;
|
||||
CharSequence expectedPongTranslation;
|
||||
|
||||
PingTranslationTestCase(final Locale givenLocale, final String expectedPongTranslation) {
|
||||
PongTranslationTestCase(final Locale givenLocale, final String expectedPongTranslation) {
|
||||
this.givenLocale = givenLocale;
|
||||
this.expectedPongTranslation = expectedPongTranslation;
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(PingTranslationTestCase.class)
|
||||
void pingRepliesWithTranslatedPongResponse(final PingTranslationTestCase testCase) {
|
||||
@EnumSource(PongTranslationTestCase.class)
|
||||
void pongRepliesWithTranslatedPongResponse(final PongTranslationTestCase testCase) {
|
||||
final var responseBody = RestAssured // @formatter:off
|
||||
.given()
|
||||
.header("Authorization", "Bearer superuser-alex@hostsharing.net")
|
||||
.header("Accept-Language", testCase.givenLocale)
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/ping")
|
||||
.get("http://localhost/api/pong")
|
||||
.then().log().all().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("text/plain;charset=UTF-8")
|
||||
.extract().body().asString();
|
||||
// @formatter:on
|
||||
// @formatter:on
|
||||
|
||||
assertThat(responseBody).isEqualTo(testCase.expectedPongTranslation + "\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
void pingRepliesWithTranslatedPongResponse() {
|
||||
final var responseBody = RestAssured // @formatter:off
|
||||
.given()
|
||||
.header("Accept-Language", Locale.GERMAN)
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/ping")
|
||||
.then().log().all().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("text/plain;charset=UTF-8")
|
||||
.extract().body().asString();
|
||||
// @formatter:on
|
||||
|
||||
assertThat(responseBody).isEqualTo("pinged - auf Deutsch\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ class PingControllerRestTest {
|
||||
|
||||
@RequiredArgsConstructor
|
||||
enum I18nTestCases {
|
||||
EN("en", "pong anonymousUser - in English"),
|
||||
DE("de", "pong anonymousUser - auf Deutsch");
|
||||
EN("en", "pinged - in English"),
|
||||
DE("de", "pinged - auf Deutsch");
|
||||
|
||||
final String language;
|
||||
final String expectedTranslation;
|
||||
|
||||
Reference in New Issue
Block a user