You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2022/01/31 11:57:19 UTC
[isis] branch master updated: ISIS-2952: impl. support f. declarative InteractionContext specification
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push:
new aaa70ec ISIS-2952: impl. support f. declarative InteractionContext specification
aaa70ec is described below
commit aaa70ec47614dbdcdfe2a4ae272080ce50df208b
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Jan 31 12:56:35 2022 +0100
ISIS-2952: impl. support f. declarative InteractionContext specification
---
.../org/apache/isis/applib/clock/VirtualClock.java | 2 +-
.../progmodel/ProgrammingModelConstants.java | 29 +++++++
.../testdomain/interact/CustomContextTest.java | 91 ++++++++++++++++++++++
.../applib/IsisInteractionHandler.java | 11 ++-
.../testing/integtestsupport/applib/_Helper.java | 13 ++++
.../applib/annotation/TestWith.java | 74 ++++++++++++++++++
.../applib/annotation/TestWithUtils.java | 54 +++++++++++++
7 files changed, 270 insertions(+), 4 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/isis/applib/clock/VirtualClock.java b/api/applib/src/main/java/org/apache/isis/applib/clock/VirtualClock.java
index 9a638ac..5dda8a5 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/clock/VirtualClock.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/clock/VirtualClock.java
@@ -142,7 +142,7 @@ public interface VirtualClock extends Serializable {
}
static VirtualClock frozenAt(@NonNull final java.time.LocalDateTime frozenAt) {
- return frozenAt(Instant.from(frozenAt));
+ return frozenAt(Instant.from(frozenAt.atZone(ZoneId.systemDefault())));
}
static VirtualClock frozenAt(@NonNull final java.time.OffsetDateTime frozenAt) {
diff --git a/core/config/src/main/java/org/apache/isis/core/config/progmodel/ProgrammingModelConstants.java b/core/config/src/main/java/org/apache/isis/core/config/progmodel/ProgrammingModelConstants.java
index b62bbe6..cb8b7d4 100644
--- a/core/config/src/main/java/org/apache/isis/core/config/progmodel/ProgrammingModelConstants.java
+++ b/core/config/src/main/java/org/apache/isis/core/config/progmodel/ProgrammingModelConstants.java
@@ -24,6 +24,8 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
@@ -122,6 +124,33 @@ public final class ProgrammingModelConstants {
}
}
+ // -- CANONICAL DATE-TIME PARSING/FORMATTING
+
+ @RequiredArgsConstructor
+ public enum DateTimeFormat {
+ /**
+ * Format: "yyyy-MM-dd HH:mm:ss"
+ * eg. {@literal "2010-01-01 13:02:04"}
+ */
+ CANONICAL(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+
+ // while this enum only has a single value, we just provide a (quasi) static method here
+ public LocalDateTime parseDateTime(final String dateTimeLiteral) {
+ return LocalDateTime.parse(dateTimeLiteral, dtf);
+ }
+
+ // while this enum only has a single value, we just provide a (quasi) static method here
+ public String formatDateTime(final LocalDateTime dateTime) {
+ return dtf.format(dateTime);
+ }
+
+ // -- HELPER
+
+ private final DateTimeFormatter dtf;
+
+ }
+
+
// -- MIXIN CONSTRUCTION
public enum MixinConstructor {
diff --git a/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/CustomContextTest.java b/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/CustomContextTest.java
new file mode 100644
index 0000000..32ef64d
--- /dev/null
+++ b/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/CustomContextTest.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.testdomain.interact;
+
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.util.Locale;
+
+import javax.inject.Inject;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.isis.applib.services.iactnlayer.InteractionService;
+import org.apache.isis.core.config.presets.IsisPresets;
+import org.apache.isis.core.config.progmodel.ProgrammingModelConstants.DateTimeFormat;
+import org.apache.isis.testdomain.conf.Configuration_headless;
+import org.apache.isis.testdomain.model.interaction.Configuration_usingInteractionDomain;
+import org.apache.isis.testing.integtestsupport.applib.IsisIntegrationTestAbstract;
+import org.apache.isis.testing.integtestsupport.applib.annotation.TestWith;
+
+import lombok.val;
+
+@SpringBootTest(
+ classes = {
+ Configuration_headless.class,
+ Configuration_usingInteractionDomain.class
+ },
+ properties = {
+ })
+@TestPropertySource({
+ IsisPresets.SilenceMetaModel,
+ IsisPresets.SilenceProgrammingModel
+})
+class CustomContextTest extends IsisIntegrationTestAbstract {
+
+ @Inject InteractionService interactionService;
+
+ @Test
+ @TestWith()
+ void shouldRunWithDefaultContext() {
+
+ val iaCtx = interactionService.currentInteractionContextElseFail();
+
+ assertTrue(iaCtx.getUser().isSystem());
+ assertEquals(Locale.getDefault(), iaCtx.getLocale().getLanguageLocale());
+ assertTrue(
+ Duration
+ .between(LocalDateTime.now(), iaCtx.getClock().nowAsLocalDateTime())
+ .abs()
+ .toSeconds() <= 5L);
+ }
+
+
+ @Test
+ @TestWith(
+ userName = "sven",
+ localeName = "fr",
+ frozenDateTime = "2010-01-01 13:02:04")
+ void shouldRunWithCustomContext() {
+
+ val iaCtx = interactionService.currentInteractionContextElseFail();
+
+ assertEquals("sven", iaCtx.getUser().getName());
+ assertEquals(Locale.FRANCE.getLanguage(), iaCtx.getLocale().getLanguageLocale().getLanguage());
+ assertEquals(
+ DateTimeFormat.CANONICAL.parseDateTime("2010-01-01 13:02:04"),
+ iaCtx.getClock().nowAsLocalDateTime());
+ }
+
+}
diff --git a/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/IsisInteractionHandler.java b/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/IsisInteractionHandler.java
index 031bfbd..899bb36 100644
--- a/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/IsisInteractionHandler.java
+++ b/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/IsisInteractionHandler.java
@@ -30,13 +30,18 @@ import org.apache.isis.applib.services.iactnlayer.InteractionService;
public class IsisInteractionHandler implements BeforeEachCallback, AfterEachCallback {
@Override
- public void beforeEach(ExtensionContext extensionContext) throws Exception {
+ public void beforeEach(final ExtensionContext extensionContext) throws Exception {
_Helper.getInteractionFactory(extensionContext)
- .ifPresent(InteractionService::openInteraction);
+ .ifPresent(interactionService->
+ _Helper
+ .getCustomInteractionContext(extensionContext)
+ .ifPresentOrElse(
+ customInteractionContext->interactionService.openInteraction(customInteractionContext),
+ interactionService::openInteraction));
}
@Override
- public void afterEach(ExtensionContext extensionContext) throws Exception {
+ public void afterEach(final ExtensionContext extensionContext) throws Exception {
_Helper.getInteractionFactory(extensionContext)
.ifPresent(InteractionService::closeInteractionLayers);
}
diff --git a/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/_Helper.java b/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/_Helper.java
index 8c93098..949f905 100644
--- a/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/_Helper.java
+++ b/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/_Helper.java
@@ -23,8 +23,12 @@ import java.util.Optional;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.apache.isis.applib.services.exceprecog.ExceptionRecognizerService;
+import org.apache.isis.applib.services.iactnlayer.InteractionContext;
import org.apache.isis.applib.services.iactnlayer.InteractionService;
import org.apache.isis.applib.services.registry.ServiceRegistry;
+import org.apache.isis.commons.internal.reflection._Annotations;
+import org.apache.isis.testing.integtestsupport.applib.annotation.TestWith;
+import org.apache.isis.testing.integtestsupport.applib.annotation.TestWithUtils;
class _Helper {
@@ -35,6 +39,15 @@ class _Helper {
.map(IsisIntegrationTestAbstract::getServiceRegistry);
}
+ /**
+ * Eg. as declared on test method via {@link TestWith}.
+ */
+ static Optional<InteractionContext> getCustomInteractionContext(final ExtensionContext extensionContext) {
+ return extensionContext.getTestMethod()
+ .flatMap(testMethod->_Annotations.synthesize(testMethod, TestWith.class))
+ .map(TestWithUtils::toInteractionContext);
+ }
+
// -- SHORTCUTS
static Optional<InteractionService> getInteractionFactory(final ExtensionContext extensionContext) {
diff --git a/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/annotation/TestWith.java b/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/annotation/TestWith.java
new file mode 100644
index 0000000..d094f4a
--- /dev/null
+++ b/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/annotation/TestWith.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.testing.integtestsupport.applib.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Locale;
+
+import org.apache.isis.applib.services.iactnlayer.InteractionContext;
+import org.apache.isis.applib.services.iactnlayer.InteractionService;
+
+/**
+ * Offers an alternative to {@link InteractionService}'s imperative approach to switch
+ * the {@link InteractionContext} for a given block of <i>JUnit</i> test code.
+ * <p>
+ * Example:<br>
+ * <pre>
+ * @Test
+ * @TestWith(
+ * userName = "sven",
+ * localeName = "en",
+ * frozenDateTime = "2010-01-01 13:02:04")
+ * void test() {
+ * // ...
+ * }
+ * </pre>
+ */
+@Inherited
+@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface TestWith {
+
+ /**
+ * If empty, defaults to the system user (with elevated privileges).
+ */
+ String userName()
+ default ""; // unspecified
+
+ /**
+ * The {@link Locale} language tag. Eg. "en", "fr", "de", ...
+ * If empty, defaults to current system locale.
+ * @see Locale#forLanguageTag(String)
+ */
+ String localeName()
+ default ""; // unspecified
+
+ /**
+ * If empty, defaults to current system time.
+ * Format: "yyyy-MM-dd HH:mm:ss"
+ * eg. {@literal "2010-01-01 13:02:04"}
+ */
+ String frozenDateTime()
+ default ""; // unspecified
+
+}
diff --git a/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/annotation/TestWithUtils.java b/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/annotation/TestWithUtils.java
new file mode 100644
index 0000000..d1813b8
--- /dev/null
+++ b/testing/integtestsupport/applib/src/main/java/org/apache/isis/testing/integtestsupport/applib/annotation/TestWithUtils.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.testing.integtestsupport.applib.annotation;
+
+import java.util.Locale;
+
+import org.apache.isis.applib.clock.VirtualClock;
+import org.apache.isis.applib.locale.UserLocale;
+import org.apache.isis.applib.services.iactnlayer.InteractionContext;
+import org.apache.isis.applib.services.user.UserMemento;
+import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.core.config.progmodel.ProgrammingModelConstants.DateTimeFormat;
+
+import lombok.val;
+import lombok.experimental.UtilityClass;
+
+@UtilityClass
+public class TestWithUtils {
+
+ public InteractionContext toInteractionContext(final TestWith testWith) {
+ val user = _Strings.isNotEmpty(testWith.userName())
+ ? UserMemento.ofName(testWith.userName())
+ : UserMemento.system();
+
+ val mainLocale = _Strings.isNotEmpty(testWith.localeName())
+ ? Locale.forLanguageTag(testWith.localeName())
+ : Locale.getDefault();
+
+ val virtualClock = _Strings.isNotEmpty(testWith.frozenDateTime())
+ ? VirtualClock.frozenAt(DateTimeFormat.CANONICAL.parseDateTime(testWith.frozenDateTime()))
+ : VirtualClock.system();
+
+ return InteractionContext.ofUserWithSystemDefaults(user)
+ .withLocale(UserLocale.valueOf(mainLocale))
+ .withClock(virtualClock);
+ }
+
+}