View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.fit;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.fail;
24  
25  import com.fasterxml.jackson.databind.JsonNode;
26  import com.fasterxml.jackson.databind.json.JsonMapper;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.io.Serializable;
30  import java.lang.reflect.Method;
31  import java.util.Properties;
32  import java.util.Set;
33  import java.util.stream.Collectors;
34  import javax.ws.rs.core.MediaType;
35  import org.apache.commons.lang3.StringUtils;
36  import org.apache.cxf.jaxrs.client.WebClient;
37  import org.apache.syncope.common.rest.api.service.SyncopeService;
38  import org.apache.wicket.Component;
39  import org.apache.wicket.MarkupContainer;
40  import org.apache.wicket.behavior.AbstractAjaxBehavior;
41  import org.apache.wicket.core.util.lang.PropertyResolver;
42  import org.apache.wicket.feedback.ExactLevelFeedbackMessageFilter;
43  import org.apache.wicket.feedback.FeedbackMessage;
44  import org.apache.wicket.markup.html.list.ListItem;
45  import org.apache.wicket.util.tester.WicketTester;
46  import org.apache.wicket.util.visit.IVisit;
47  import org.junit.jupiter.api.BeforeAll;
48  import org.slf4j.Logger;
49  import org.slf4j.LoggerFactory;
50  
51  public abstract class AbstractUIITCase {
52  
53      protected static final Logger LOG = LoggerFactory.getLogger(AbstractUIITCase.class);
54  
55      protected static final JsonMapper JSON_MAPPER = JsonMapper.builder().findAndAddModules().build();
56  
57      protected static final String ADMIN_UNAME = "admin";
58  
59      protected static final String ADMIN_PWD = "password";
60  
61      protected static final String ADDRESS = "http://localhost:9080/syncope/rest";
62  
63      protected static final String KEY = "key";
64  
65      protected static final String SCHEMA = "schema";
66  
67      protected static String ANONYMOUS_UNAME;
68  
69      protected static String ANONYMOUS_KEY;
70  
71      protected static WicketTester TESTER;
72  
73      protected static SyncopeService SYNCOPE_SERVICE;
74  
75      protected static boolean IS_FLOWABLE_ENABLED = false;
76  
77      protected static boolean IS_EXT_SEARCH_ENABLED = false;
78  
79      @BeforeAll
80      public static void anonymousSetup() throws IOException {
81          try (InputStream propStream = AbstractITCase.class.getResourceAsStream("/core.properties")) {
82              Properties props = new Properties();
83              props.load(propStream);
84  
85              ANONYMOUS_UNAME = props.getProperty("security.anonymousUser");
86              ANONYMOUS_KEY = props.getProperty("security.anonymousKey");
87          } catch (Exception e) {
88              LOG.error("Could not read core.properties", e);
89          }
90  
91          assertNotNull(ANONYMOUS_UNAME);
92          assertNotNull(ANONYMOUS_KEY);
93  
94          JsonNode beans = JSON_MAPPER.readTree(
95                  (InputStream) WebClient.create(
96                          StringUtils.substringBeforeLast(ADDRESS, "/") + "/actuator/beans",
97                          ANONYMOUS_UNAME,
98                          ANONYMOUS_KEY,
99                          null).
100                         accept(MediaType.APPLICATION_JSON).get().getEntity());
101 
102         JsonNode uwfAdapter = beans.findValues("uwfAdapter").get(0);
103         IS_FLOWABLE_ENABLED = uwfAdapter.get("resource").asText().contains("Flowable");
104 
105         JsonNode anySearchDAO = beans.findValues("anySearchDAO").get(0);
106         IS_EXT_SEARCH_ENABLED = anySearchDAO.get("type").asText().contains("Elasticsearch")
107                 || anySearchDAO.get("type").asText().contains("OpenSearch");
108     }
109 
110     protected static <V extends Serializable> Component findComponentByProp(
111             final String property, final String path, final V key) {
112 
113         Component component = TESTER.getComponentFromLastRenderedPage(path);
114         return (component instanceof MarkupContainer ? MarkupContainer.class.cast(component) : component.getPage()).
115                 visitChildren(ListItem.class, (ListItem<?> object, IVisit<Component> visit) -> {
116                     try {
117                         Method getter = PropertyResolver.getPropertyGetter(property, object.getModelObject());
118                         if (getter != null && getter.invoke(object.getModelObject()).equals(key)) {
119                             visit.stop(object);
120                         }
121                     } catch (Exception e) {
122                         LOG.debug("Error finding component by property ({},{}) on path {}", property, key, path, e);
123                     }
124                 });
125     }
126 
127     protected static <V extends Serializable> Component findComponentByPropNotNull(
128             final String property, final String path) {
129 
130         Component component = TESTER.getComponentFromLastRenderedPage(path);
131         return (component instanceof MarkupContainer ? MarkupContainer.class.cast(component) : component.getPage()).
132                 visitChildren(ListItem.class, (ListItem<?> object, IVisit<Component> visit) -> {
133                     try {
134                         Method getter = PropertyResolver.getPropertyGetter(property, object.getModelObject());
135                         if (getter != null && getter.invoke(object.getModelObject()) != null) {
136                             visit.stop(object);
137                         }
138                     } catch (Exception e) {
139                         LOG.debug("Error finding component by property {} not null on path {}", property, path, e);
140                     }
141                 });
142     }
143 
144     protected static Component findComponentById(final String searchPath, final String id) {
145         Component component = TESTER.getComponentFromLastRenderedPage(searchPath);
146         return (component instanceof MarkupContainer ? MarkupContainer.class.cast(component) : component.getPage()).
147                 visitChildren(Component.class, (object, visit) -> {
148                     if (object.getId().equals(id)) {
149                         visit.stop(object);
150                     }
151                 });
152     }
153 
154     protected static Component findComponentByMarkupId(final String searchPath, final String markupId) {
155         Component component = TESTER.getComponentFromLastRenderedPage(searchPath);
156         return (component instanceof MarkupContainer ? MarkupContainer.class.cast(component) : component.getPage()).
157                 visitChildren(Component.class, (object, visit) -> {
158                     if (object.getMarkupId().equals(markupId)) {
159                         visit.stop(object);
160                     }
161                 });
162     }
163 
164     protected static void closeCallBack(final Component modal) {
165         modal.getBehaviors().stream().
166                 filter(behavior -> (behavior instanceof AbstractAjaxBehavior)).
167                 forEachOrdered(behavior -> TESTER.executeBehavior((AbstractAjaxBehavior) behavior));
168     }
169 
170     protected static void assertSuccessMessage() {
171         Set<Serializable> messages = TESTER.getFeedbackMessages(
172                 new ExactLevelFeedbackMessageFilter(FeedbackMessage.SUCCESS)).stream().
173                 map(FeedbackMessage::getMessage).collect(Collectors.toSet());
174         if (messages.size() != 1) {
175             fail("Expected single message but found " + messages);
176         }
177         assertEquals("Operation successfully executed", messages.iterator().next());
178     }
179 }