import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.Users.CurrentWsResponse.Permissions;
import static org.sonarqube.ws.Users.CurrentWsResponse.newBuilder;
-import static org.sonarqube.ws.Users.CurrentWsResponse.HomepageType.MY_PROJECTS;
import static org.sonarqube.ws.Users.CurrentWsResponse.HomepageType.ORGANIZATION;
import static org.sonarqube.ws.Users.CurrentWsResponse.HomepageType.PROJECT;
import static org.sonarqube.ws.client.user.UsersWsParameters.ACTION_CURRENT;
private final DbClient dbClient;
private final DefaultOrganizationProvider defaultOrganizationProvider;
private final AvatarResolver avatarResolver;
+ private final HomepageTypes homepageTypes;
public CurrentAction(UserSession userSession, DbClient dbClient, DefaultOrganizationProvider defaultOrganizationProvider,
- AvatarResolver avatarResolver) {
+ AvatarResolver avatarResolver, HomepageTypes homepageTypes) {
this.userSession = userSession;
this.dbClient = dbClient;
this.defaultOrganizationProvider = defaultOrganizationProvider;
this.avatarResolver = avatarResolver;
+ this.homepageTypes = homepageTypes;
}
@Override
}
}
- private static CurrentWsResponse.Homepage defaultHomepage() {
+ private CurrentWsResponse.Homepage defaultHomepage() {
return CurrentWsResponse.Homepage.newBuilder()
- .setType(MY_PROJECTS)
+ .setType(CurrentWsResponse.HomepageType.valueOf(homepageTypes.getDefaultType().name()))
.build();
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.user.ws;
-
-import java.util.List;
-
-import static java.util.Arrays.stream;
-import static java.util.stream.Collectors.toList;
-
-public enum HomepageType {
-
- PROJECT, ORGANIZATION, MY_PROJECTS, MY_ISSUES;
-
- public static List<String> keys() {
- return stream(values()).map(Enum::toString).collect(toList());
- }
-}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.user.ws;
+
+import java.util.List;
+
+public interface HomepageTypes {
+
+ enum Type {
+ PROJECT,
+ /**
+ * This type in only available on SonarQube
+ */
+ PROJECTS,
+ /**
+ * These types are only available on SonarCloud
+ */
+ MY_PROJECTS, MY_ISSUES,
+ /**
+ * This type in only available when organizations are enabled
+ */
+ ORGANIZATION
+ }
+
+ List<Type> getTypes();
+
+ Type getDefaultType();
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.user.ws;
+
+import java.util.EnumSet;
+import java.util.List;
+import org.sonar.api.Startable;
+import org.sonar.api.config.Configuration;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.process.ProcessProperties;
+import org.sonar.server.organization.OrganizationFlags;
+
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Arrays.stream;
+import static java.util.stream.Collectors.toList;
+import static org.sonar.server.user.ws.HomepageTypes.Type.MY_ISSUES;
+import static org.sonar.server.user.ws.HomepageTypes.Type.MY_PROJECTS;
+import static org.sonar.server.user.ws.HomepageTypes.Type.ORGANIZATION;
+import static org.sonar.server.user.ws.HomepageTypes.Type.PROJECT;
+import static org.sonar.server.user.ws.HomepageTypes.Type.PROJECTS;
+import static org.sonar.server.user.ws.HomepageTypes.Type.values;
+
+public class HomepageTypesImpl implements HomepageTypes, Startable {
+
+ private static final EnumSet<Type> ON_SONARQUBE = EnumSet.of(PROJECTS, PROJECT, ORGANIZATION);
+ private static final EnumSet<Type> ON_SONARCLOUD = EnumSet.of(PROJECT, MY_PROJECTS, MY_ISSUES, ORGANIZATION);
+
+ private final Configuration configuration;
+ private final OrganizationFlags organizationFlags;
+ private final DbClient dbClient;
+
+ private List<Type> types;
+ private Type defaultType;
+
+ public HomepageTypesImpl(Configuration configuration, OrganizationFlags organizationFlags, DbClient dbClient) {
+ this.configuration = configuration;
+ this.organizationFlags = organizationFlags;
+ this.dbClient = dbClient;
+ }
+
+ @Override
+ public List<Type> getTypes() {
+ checkState(types != null, "Homepage types have not been initialized yet");
+ return types;
+ }
+
+ @Override
+ public Type getDefaultType() {
+ checkState(types != null, "Homepage types have not been initialized yet");
+ return defaultType;
+ }
+
+ @Override
+ public void start() {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ boolean isOnSonarCloud = configuration.getBoolean(ProcessProperties.Property.SONARCLOUD_ENABLED.getKey()).orElse(false);
+ boolean isOrganizationEnabled = organizationFlags.isEnabled(dbSession);
+ this.types = stream(values())
+ .filter(type -> (isOnSonarCloud && ON_SONARCLOUD.contains(type)) || (!isOnSonarCloud && ON_SONARQUBE.contains(type)))
+ .filter(type -> isOrganizationEnabled || !(type.equals(ORGANIZATION)))
+ .collect(toList());
+ this.defaultType = isOnSonarCloud ? Type.MY_PROJECTS : PROJECTS;
+ }
+ }
+
+ @Override
+ public void stop() {
+ // Nothing to do
+ }
+}
import static java.lang.String.format;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.apache.commons.lang.StringUtils.isNotBlank;
-import static org.sonar.server.user.ws.HomepageType.ORGANIZATION;
-import static org.sonar.server.user.ws.HomepageType.PROJECT;
-import static org.sonar.server.user.ws.HomepageType.keys;
-import static org.sonar.server.user.ws.HomepageType.valueOf;
+import static org.sonar.server.user.ws.HomepageTypes.Type.ORGANIZATION;
+import static org.sonar.server.user.ws.HomepageTypes.Type.PROJECT;
import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
private final UserSession userSession;
private final DbClient dbClient;
private final ComponentFinder componentFinder;
+ private HomepageTypes homepageTypes;
- public SetHomepageAction(UserSession userSession, DbClient dbClient, ComponentFinder componentFinder) {
+ public SetHomepageAction(UserSession userSession, DbClient dbClient, ComponentFinder componentFinder, HomepageTypes homepageTypes) {
this.userSession = userSession;
this.dbClient = dbClient;
this.componentFinder = componentFinder;
+ this.homepageTypes = homepageTypes;
}
@Override
action.createParam(PARAM_TYPE)
.setDescription("Type of the requested page")
.setRequired(true)
- .setPossibleValues(keys());
+ .setPossibleValues(homepageTypes.getTypes());
action.createParam(PARAM_ORGANIZATION)
.setDescription("Organization key. It should only be used when parameter '%s' is set to '%s'", PARAM_TYPE, ORGANIZATION)
@Override
public void handle(Request request, Response response) throws Exception {
userSession.checkLoggedIn();
- HomepageType type = valueOf(request.mandatoryParam(PARAM_TYPE));
+ HomepageTypes.Type type = request.mandatoryParamAsEnum(PARAM_TYPE, HomepageTypes.Type.class);
String componentParameter = request.param(PARAM_COMPONENT);
String organizationParameter = request.param(PARAM_ORGANIZATION);
}
@CheckForNull
- private String getHomepageParameter(DbSession dbSession, HomepageType type, @Nullable String componentParameter, @Nullable String branchParameter,
+ private String getHomepageParameter(DbSession dbSession, HomepageTypes.Type type, @Nullable String componentParameter, @Nullable String branchParameter,
@Nullable String organizationParameter) {
switch (type) {
case PROJECT:
UserPropertiesWs.class,
UserJsonWriter.class,
SkipOnboardingTutorialAction.class,
- SetHomepageAction.class);
+ SetHomepageAction.class,
+ HomepageTypesImpl.class);
}
}
*/
package org.sonar.server.user.ws;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
import static org.sonar.db.permission.OrganizationPermission.PROVISION_PROJECTS;
import static org.sonar.db.permission.OrganizationPermission.SCAN;
import static org.sonar.db.user.GroupTesting.newGroupDto;
import static org.sonar.test.JsonAssert.assertJson;
-import static org.sonarqube.ws.Users.CurrentWsResponse.HomepageType.MY_PROJECTS;
public class CurrentActionTest {
@Rule
private DbClient dbClient = db.getDbClient();
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
- private WsActionTester ws = new WsActionTester(new CurrentAction(userSessionRule, dbClient, defaultOrganizationProvider, new AvatarResolverImpl()));
+ private HomepageTypes homepageTypes = mock(HomepageTypes.class);
+
+ private WsActionTester ws = new WsActionTester(new CurrentAction(userSessionRule, dbClient, defaultOrganizationProvider, new AvatarResolverImpl(), homepageTypes));
+
+ @Before
+ public void setUp() {
+ when(homepageTypes.getDefaultType()).thenReturn(HomepageTypes.Type.MY_PROJECTS);
+ ws = new WsActionTester(new CurrentAction(userSessionRule, dbClient, defaultOrganizationProvider, new AvatarResolverImpl(), homepageTypes));
+ }
@Test
public void return_user_info() {
assertThat(response.getHomepage())
.extracting(CurrentWsResponse.Homepage::getType)
- .containsExactly(MY_PROJECTS);
+ .containsExactly(CurrentWsResponse.HomepageType.MY_PROJECTS);
}
@Test
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.user.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.db.DbTester;
+import org.sonar.server.organization.TestOrganizationFlags;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+import static org.sonar.server.user.ws.HomepageTypes.Type.MY_ISSUES;
+import static org.sonar.server.user.ws.HomepageTypes.Type.MY_PROJECTS;
+import static org.sonar.server.user.ws.HomepageTypes.Type.ORGANIZATION;
+import static org.sonar.server.user.ws.HomepageTypes.Type.PROJECT;
+import static org.sonar.server.user.ws.HomepageTypes.Type.PROJECTS;
+
+public class HomepageTypesImplTest {
+
+ @Rule
+ public DbTester db = DbTester.create();
+
+ private MapSettings settings = new MapSettings();
+ private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
+
+ private HomepageTypesImpl underTest = new HomepageTypesImpl(settings.asConfig(), organizationFlags, db.getDbClient());
+
+ @Test
+ public void types_on_sonarcloud_and_organization_disabled() {
+ settings.setProperty("sonar.sonarcloud.enabled", true);
+ organizationFlags.setEnabled(false);
+
+ underTest.start();
+
+ assertThat(underTest.getTypes()).containsExactlyInAnyOrder(PROJECT, MY_PROJECTS, MY_ISSUES);
+ }
+
+ @Test
+ public void types_on_sonarcloud_and_organization_enabled() {
+ settings.setProperty("sonar.sonarcloud.enabled", true);
+ organizationFlags.setEnabled(true);
+
+ underTest.start();
+
+ assertThat(underTest.getTypes()).containsExactlyInAnyOrder(PROJECT, MY_PROJECTS, MY_ISSUES, ORGANIZATION);
+ }
+
+ @Test
+ public void types_on_sonarqube_and_organization_disabled() {
+ settings.setProperty("sonar.sonarcloud.enabled", false);
+ organizationFlags.setEnabled(false);
+
+ underTest.start();
+
+ assertThat(underTest.getTypes()).containsExactlyInAnyOrder(PROJECT, PROJECTS);
+ }
+
+ @Test
+ public void types_on_sonarqube_and_organization_enabled() {
+ settings.setProperty("sonar.sonarcloud.enabled", false);
+ organizationFlags.setEnabled(true);
+
+ underTest.start();
+
+ assertThat(underTest.getTypes()).containsExactlyInAnyOrder(PROJECT, PROJECTS, ORGANIZATION);
+ }
+
+ @Test
+ public void default_type_on_sonarcloud() {
+ settings.setProperty("sonar.sonarcloud.enabled", true);
+
+ underTest.start();
+
+ assertThat(underTest.getDefaultType()).isEqualTo(MY_PROJECTS);
+ }
+
+ @Test
+ public void default_type_on_sonarqube() {
+ settings.setProperty("sonar.sonarcloud.enabled", false);
+
+ underTest.start();
+
+ assertThat(underTest.getDefaultType()).isEqualTo(PROJECTS);
+ }
+
+}
*/
package org.sonar.server.user.ws;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;
+import static java.util.Arrays.asList;
import static org.apache.http.HttpStatus.SC_NO_CONTENT;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.server.user.ws.HomepageTypes.Type.MY_ISSUES;
+import static org.sonar.server.user.ws.HomepageTypes.Type.MY_PROJECTS;
+import static org.sonar.server.user.ws.HomepageTypes.Type.ORGANIZATION;
+import static org.sonar.server.user.ws.HomepageTypes.Type.PROJECT;
public class SetHomepageActionTest {
public ExpectedException expectedException = ExpectedException.none();
private DbClient dbClient = db.getDbClient();
- private SetHomepageAction underTest = new SetHomepageAction(userSession, dbClient, TestComponentFinder.from(db));
- private WsActionTester ws = new WsActionTester(underTest);
+ private HomepageTypes homepageTypes = mock(HomepageTypes.class);
+
+ private WsActionTester ws;
+
+ @Before
+ public void setUp() {
+ when(homepageTypes.getTypes()).thenReturn(asList(PROJECT, ORGANIZATION, MY_ISSUES, MY_PROJECTS));
+ ws = new WsActionTester(new SetHomepageAction(userSession, dbClient, TestComponentFinder.from(db), homepageTypes));
+ }
@Test
public void verify_definition() {
assertThat(action.since()).isEqualTo("7.0");
assertThat(action.description()).isEqualTo("Set homepage of current user.<br> Requires authentication.");
assertThat(action.responseExample()).isNull();
- assertThat(action.handler()).isSameAs(underTest);
assertThat(action.params()).hasSize(4);
WebService.Param typeParam = action.param("type");
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new UsersWsModule().configure(container);
- assertThat(container.size()).isEqualTo(2 + 13);
+ assertThat(container.size()).isEqualTo(2 + 14);
}
}
import org.sonar.api.server.ws.WebService;
import org.sonar.db.DbClient;
import org.sonar.server.issue.ws.AvatarResolver;
-import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.user.UserUpdater;
import org.sonar.server.user.index.UserIndex;
WsTester tester = new WsTester(new UsersWs(
new CreateAction(mock(DbClient.class), mock(UserUpdater.class), userSessionRule),
new UpdateAction(mock(UserUpdater.class), userSessionRule, mock(UserJsonWriter.class), mock(DbClient.class)),
- new CurrentAction(userSessionRule, mock(DbClient.class), mock(DefaultOrganizationProvider.class), mock(AvatarResolver.class)),
new ChangePasswordAction(mock(DbClient.class), mock(UserUpdater.class), userSessionRule),
new SearchAction(userSessionRule, mock(UserIndex.class), mock(DbClient.class), mock(AvatarResolver.class))));
controller = tester.controller("api/users");
assertThat(controller).isNotNull();
assertThat(controller.description()).isNotEmpty();
assertThat(controller.since()).isEqualTo("3.6");
- assertThat(controller.actions()).hasSize(5);
+ assertThat(controller.actions()).hasSize(4);
}
@Test
assertThat(action.params()).hasSize(3);
}
- @Test
- public void define_current_action() {
- WebService.Action action = controller.action("current");
- assertThat(action).isNotNull();
- assertThat(action.isPost()).isFalse();
- assertThat(action.isInternal()).isTrue();
- assertThat(action.params()).isEmpty();
- }
}
ORGANIZATION = 2;
MY_PROJECTS = 3;
MY_ISSUES = 4;
+ PROJECTS = 5;
}
message Homepage {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonarqube.tests.user;
+
+import com.sonar.orchestrator.Orchestrator;
+import javax.annotation.Nullable;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonarqube.qa.util.Tester;
+import org.sonarqube.ws.Projects.CreateWsResponse.Project;
+import org.sonarqube.ws.Users;
+import org.sonarqube.ws.Users.CreateWsResponse.User;
+import org.sonarqube.ws.Users.CurrentWsResponse.HomepageType;
+import org.sonarqube.ws.client.PostRequest;
+import org.sonarqube.ws.client.projects.DeleteRequest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonarqube.ws.Users.CurrentWsResponse.HomepageType.PROJECT;
+import static org.sonarqube.ws.Users.CurrentWsResponse.HomepageType.PROJECTS;
+
+public class HomepageTest {
+
+ @ClassRule
+ public static final Orchestrator orchestrator = UserSuite.ORCHESTRATOR;
+
+ @Rule
+ public Tester tester = new Tester(orchestrator).disableOrganizations();
+
+ @Test
+ public void default_homepage() {
+ User user = tester.users().generate();
+
+ checkHomepage(user, PROJECTS, null);
+ }
+
+ @Test
+ public void set_and_get_homepage() {
+ Project project = tester.projects().provision();
+ User user = tester.users().generate();
+
+ setHomepage(user, "PROJECT", project.getKey());
+
+ checkHomepage(user, PROJECT, project);
+ }
+
+ @Test
+ public void fallback_to_projects_when_homepage_was_set_to_a_removed_project() {
+ User user = tester.users().generate();
+ Project project = tester.projects().provision();
+ setHomepage(user, "PROJECT", project.getKey());
+ checkHomepage(user, PROJECT, project);
+
+ tester.wsClient().projects().delete(new DeleteRequest().setProject(project.getKey()));
+
+ checkHomepage(user, PROJECTS, null);
+ }
+
+ private void setHomepage(User user, String type, @Nullable String component) {
+ tester.as(user.getLogin()).wsClient().wsConnector().call(new PostRequest("api/users/set_homepage")
+ .setParam("type", type)
+ .setParam("component", component))
+ .failIfNotSuccessful();
+ }
+
+ private void checkHomepage(User user, HomepageType type, @Nullable Project project) {
+ Users.CurrentWsResponse current = tester.as(user.getLogin()).wsClient().users().current();
+ assertThat(current.getHomepage().getType()).isEqualTo(type);
+ if (project != null) {
+ assertThat(current.getHomepage().getComponent()).isEqualTo(project.getKey());
+ } else {
+ assertThat(current.getHomepage().hasComponent()).isFalse();
+ }
+ }
+}
BaseIdentityProviderTest.class,
FavoritesWsTest.class,
ForceAuthenticationTest.class,
+ HomepageTest.class,
LocalAuthenticationTest.class,
MyAccountPageTest.class,
NotificationsWsTest.class,