]> source.dussan.org Git - sonarqube.git/commitdiff
Rename Quality Gate WS classes
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Thu, 28 Jul 2016 09:10:44 +0000 (11:10 +0200)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Fri, 29 Jul 2016 08:54:01 +0000 (10:54 +0200)
24 files changed:
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/AppAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CopyAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateConditionAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeleteConditionAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ListAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGateWsAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesWs.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWs.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/RenameAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SetAsDefaultAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ShowAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UnsetDefaultAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UpdateConditionAction.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/AppActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QGatesWsTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java [new file with mode: 0644]

index 14dc88176119d2543d13fb8d049316edd8c2faf7..f64df96c3e82a27b778af16e4a7207a934157ed9 100644 (file)
@@ -187,7 +187,7 @@ import org.sonar.server.qualitygate.ws.DeleteConditionAction;
 import org.sonar.server.qualitygate.ws.DeselectAction;
 import org.sonar.server.qualitygate.ws.DestroyAction;
 import org.sonar.server.qualitygate.ws.ProjectStatusAction;
-import org.sonar.server.qualitygate.ws.QGatesWs;
+import org.sonar.server.qualitygate.ws.QualityGatesWs;
 import org.sonar.server.qualitygate.ws.SelectAction;
 import org.sonar.server.qualitygate.ws.SetAsDefaultAction;
 import org.sonar.server.qualitygate.ws.UnsetDefaultAction;
@@ -481,7 +481,7 @@ public class PlatformLevel4 extends PlatformLevel {
       UpdateConditionAction.class,
       org.sonar.server.qualitygate.ws.AppAction.class,
       ProjectStatusAction.class,
-      QGatesWs.class,
+      QualityGatesWs.class,
 
       // web services
       WebServiceEngine.class,
index 81e5ec071abcff79be7ea90603ade1a0746712ae..90aa2d27707c1795ca15c0961e861d2bd65c8baa 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class AppAction implements QGateWsAction {
+public class AppAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
index a18f1bb8b69cf320bae64a602f3a4a37705b4eae..89e77f7998e41fdba83d0e0556aaa76c0f85ace6 100644 (file)
@@ -26,7 +26,7 @@ import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.db.qualitygate.QualityGateDto;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class CopyAction implements QGateWsAction {
+public class CopyAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
@@ -42,12 +42,12 @@ public class CopyAction implements QGateWsAction {
       .setSince("4.3")
       .setHandler(this);
 
-    action.createParam(QGatesWs.PARAM_ID)
+    action.createParam(QualityGatesWs.PARAM_ID)
       .setDescription("The ID of the source quality gate")
       .setRequired(true)
       .setExampleValue("1");
 
-    action.createParam(QGatesWs.PARAM_NAME)
+    action.createParam(QualityGatesWs.PARAM_NAME)
       .setDescription("The name of the quality gate to create")
       .setRequired(true)
       .setExampleValue("My Quality Gate");
@@ -55,9 +55,9 @@ public class CopyAction implements QGateWsAction {
 
   @Override
   public void handle(Request request, Response response) {
-    QualityGateDto newQualityGate = qualityGates.copy(QGatesWs.parseId(request, QGatesWs.PARAM_ID), request.mandatoryParam(QGatesWs.PARAM_NAME));
+    QualityGateDto newQualityGate = qualityGates.copy(QualityGatesWs.parseId(request, QualityGatesWs.PARAM_ID), request.mandatoryParam(QualityGatesWs.PARAM_NAME));
     JsonWriter writer = response.newJsonWriter();
-    QGatesWs.writeQualityGate(newQualityGate, writer).close();
+    QualityGatesWs.writeQualityGate(newQualityGate, writer).close();
   }
 
 }
index 0413a9d8beaf0cc58db21319bbbf9c23b8b76ae2..5ddc735e02bccd6afa5673b90b57f9bb560a22dd 100644 (file)
@@ -26,7 +26,7 @@ import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.db.qualitygate.QualityGateDto;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class CreateAction implements QGateWsAction {
+public class CreateAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
@@ -42,7 +42,7 @@ public class CreateAction implements QGateWsAction {
       .setPost(true)
       .setHandler(this);
 
-    action.createParam(QGatesWs.PARAM_NAME)
+    action.createParam(QualityGatesWs.PARAM_NAME)
       .setDescription("The name of the quality gate to create")
       .setRequired(true)
       .setExampleValue("My Quality Gate");
@@ -50,9 +50,9 @@ public class CreateAction implements QGateWsAction {
 
   @Override
   public void handle(Request request, Response response) {
-    QualityGateDto newQualityGate = qualityGates.create(request.mandatoryParam(QGatesWs.PARAM_NAME));
+    QualityGateDto newQualityGate = qualityGates.create(request.mandatoryParam(QualityGatesWs.PARAM_NAME));
     JsonWriter writer = response.newJsonWriter();
-    QGatesWs.writeQualityGate(newQualityGate, writer).close();
+    QualityGatesWs.writeQualityGate(newQualityGate, writer).close();
   }
 
 }
index fc77616ba0bc32c2dcfe3186a1996c4fa9b87aa7..aa572402040bd2e45d54b4f796349175bb73d0cf 100644 (file)
@@ -24,7 +24,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class CreateConditionAction implements QGateWsAction {
+public class CreateConditionAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
@@ -41,24 +41,24 @@ public class CreateConditionAction implements QGateWsAction {
       .setHandler(this);
 
     createCondition
-      .createParam(QGatesWs.PARAM_GATE_ID)
+      .createParam(QualityGatesWs.PARAM_GATE_ID)
       .setDescription("ID of the quality gate")
       .setRequired(true)
       .setExampleValue("1");
 
-    QGatesWs.addConditionParams(createCondition);
+    QualityGatesWs.addConditionParams(createCondition);
   }
 
   @Override
   public void handle(Request request, Response response) {
-    QGatesWs.writeQualityGateCondition(
+    QualityGatesWs.writeQualityGateCondition(
       qualityGates.createCondition(
-        QGatesWs.parseId(request, QGatesWs.PARAM_GATE_ID),
-        request.mandatoryParam(QGatesWs.PARAM_METRIC),
-        request.mandatoryParam(QGatesWs.PARAM_OPERATOR),
-        request.param(QGatesWs.PARAM_WARNING),
-        request.param(QGatesWs.PARAM_ERROR),
-        request.paramAsInt(QGatesWs.PARAM_PERIOD)
+        QualityGatesWs.parseId(request, QualityGatesWs.PARAM_GATE_ID),
+        request.mandatoryParam(QualityGatesWs.PARAM_METRIC),
+        request.mandatoryParam(QualityGatesWs.PARAM_OPERATOR),
+        request.param(QualityGatesWs.PARAM_WARNING),
+        request.param(QualityGatesWs.PARAM_ERROR),
+        request.paramAsInt(QualityGatesWs.PARAM_PERIOD)
         ), response.newJsonWriter()
       ).close();
   }
index ac01a7868b85e18152ed3a37f5faa51a46b06287..cd1f94f0f9a94bb64b17c59134f9b5cc9234c382 100644 (file)
@@ -24,7 +24,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class DeleteConditionAction implements QGateWsAction {
+public class DeleteConditionAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
@@ -41,7 +41,7 @@ public class DeleteConditionAction implements QGateWsAction {
       .setHandler(this);
 
     createCondition
-      .createParam(QGatesWs.PARAM_ID)
+      .createParam(QualityGatesWs.PARAM_ID)
       .setRequired(true)
       .setDescription("Condition ID")
       .setExampleValue("2");
@@ -49,7 +49,7 @@ public class DeleteConditionAction implements QGateWsAction {
 
   @Override
   public void handle(Request request, Response response) {
-    qualityGates.deleteCondition(QGatesWs.parseId(request, QGatesWs.PARAM_ID));
+    qualityGates.deleteCondition(QualityGatesWs.parseId(request, QualityGatesWs.PARAM_ID));
     response.noContent();
   }
 
index 059bbd35d6fe6f7d6bb95e6b983eb0a6a4b2a91a..1f1bfee0a4713017d53fff56d019621094c42bc2 100644 (file)
@@ -24,7 +24,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class DeselectAction implements QGateWsAction {
+public class DeselectAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
@@ -40,12 +40,12 @@ public class DeselectAction implements QGateWsAction {
       .setSince("4.3")
       .setHandler(this);
 
-    action.createParam(QGatesWs.PARAM_GATE_ID)
+    action.createParam(QualityGatesWs.PARAM_GATE_ID)
       .setDescription("Quality Gate ID")
       .setRequired(true)
       .setExampleValue("1");
 
-    action.createParam(QGatesWs.PARAM_PROJECT_ID)
+    action.createParam(QualityGatesWs.PARAM_PROJECT_ID)
       .setDescription("Project ID")
       .setRequired(true)
       .setExampleValue("12");
@@ -53,7 +53,7 @@ public class DeselectAction implements QGateWsAction {
 
   @Override
   public void handle(Request request, Response response) {
-    qualityGates.dissociateProject(QGatesWs.parseId(request, QGatesWs.PARAM_GATE_ID), QGatesWs.parseId(request, QGatesWs.PARAM_PROJECT_ID));
+    qualityGates.dissociateProject(QualityGatesWs.parseId(request, QualityGatesWs.PARAM_GATE_ID), QualityGatesWs.parseId(request, QualityGatesWs.PARAM_PROJECT_ID));
     response.noContent();
   }
 
index 27c234a36d3e7ebf287a7b3f0124c93c6fd1f042..654a693e7f07f8423e11d0815ee7128aa4c656ee 100644 (file)
@@ -24,7 +24,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class DestroyAction implements QGateWsAction {
+public class DestroyAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
@@ -40,7 +40,7 @@ public class DestroyAction implements QGateWsAction {
       .setPost(true)
       .setHandler(this);
 
-    action.createParam(QGatesWs.PARAM_ID)
+    action.createParam(QualityGatesWs.PARAM_ID)
       .setDescription("ID of the quality gate to delete")
       .setRequired(true)
       .setExampleValue("1");
@@ -48,7 +48,7 @@ public class DestroyAction implements QGateWsAction {
 
   @Override
   public void handle(Request request, Response response) {
-    qualityGates.delete(QGatesWs.parseId(request, QGatesWs.PARAM_ID));
+    qualityGates.delete(QualityGatesWs.parseId(request, QualityGatesWs.PARAM_ID));
     response.noContent();
   }
 
index aa44510fdc532a8d4c8aa5d8df54dea523a3cfc3..dd2f0a499372488e193194f341e062b721eaeea7 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.db.qualitygate.QualityGateDto;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class ListAction implements QGateWsAction {
+public class ListAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
@@ -48,7 +48,7 @@ public class ListAction implements QGateWsAction {
   public void handle(Request request, Response response) {
     JsonWriter writer = response.newJsonWriter().beginObject().name("qualitygates").beginArray();
     for (QualityGateDto qgate : qualityGates.list()) {
-      QGatesWs.writeQualityGate(qgate, writer);
+      QualityGatesWs.writeQualityGate(qgate, writer);
     }
     writer.endArray();
     QualityGateDto defaultQgate = qualityGates.getDefault();
index ce4c6acd57811542fbd71212213f4429f9f5cf5a..40b7cc507e6bdfbe9a6b02339d4eba17a5bcb49c 100644 (file)
@@ -56,7 +56,7 @@ import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_PROJECT_ID;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_PROJECT_KEY;
 
-public class ProjectStatusAction implements QGateWsAction {
+public class ProjectStatusAction implements QualityGatesWsAction {
   private static final String QG_STATUSES_ONE_LINE = Joiner.on(", ")
     .join(Lists.transform(Arrays.asList(ProjectStatusWsResponse.Status.values()), new Function<ProjectStatusWsResponse.Status, String>() {
       @Nonnull
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGateWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGateWsAction.java
deleted file mode 100644 (file)
index e162a69..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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.qualitygate.ws;
-
-import org.sonar.server.ws.WsAction;
-
-public interface QGateWsAction extends WsAction {
-
-  // Marker interface
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesWs.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QGatesWs.java
deleted file mode 100644 (file)
index 6342b7c..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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.qualitygate.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.db.qualitygate.QualityGateConditionDto;
-import org.sonar.db.qualitygate.QualityGateDto;
-import org.sonar.server.exceptions.BadRequestException;
-
-public class QGatesWs implements WebService {
-
-  static final String PARAM_PAGE_SIZE = "pageSize";
-  static final String PARAM_PAGE = "page";
-  static final String PARAM_QUERY = "query";
-  static final String PARAM_NAME = "name";
-  static final String PARAM_ERROR = "error";
-  static final String PARAM_WARNING = "warning";
-  static final String PARAM_PERIOD = "period";
-  static final String PARAM_OPERATOR = "op";
-  static final String PARAM_METRIC = "metric";
-  static final String PARAM_GATE_ID = "gateId";
-  static final String PARAM_PROJECT_ID = "projectId";
-  static final String PARAM_ID = "id";
-
-  private final QGateWsAction[] actions;
-
-  public QGatesWs(QGateWsAction... actions) {
-    this.actions = actions;
-  }
-
-  @Override
-  public void define(Context context) {
-    NewController controller = context.createController("api/qualitygates")
-      .setSince("4.3")
-      .setDescription("Manage quality gates, including conditions and project association.");
-
-    for (QGateWsAction action : actions) {
-      action.define(controller);
-    }
-
-    controller.done();
-  }
-
-  static void addConditionParams(NewAction action) {
-    action
-      .createParam(PARAM_METRIC)
-      .setDescription("Condition metric")
-      .setRequired(true)
-      .setExampleValue("blocker_violations");
-
-    action.createParam(PARAM_OPERATOR)
-      .setDescription("Condition operator:<br/>" +
-        "<ul>" +
-        "<li>EQ = equals</li>" +
-        "<li>NE = is not</li>" +
-        "<li>LT = is lower than</li>" +
-        "<li>GT = is greater than</li>" +
-        "</ui>")
-      .setExampleValue(QualityGateConditionDto.OPERATOR_EQUALS)
-      .setPossibleValues(QualityGateConditionDto.ALL_OPERATORS);
-
-    action.createParam(PARAM_PERIOD)
-      .setDescription("Condition period. If not set, the absolute value is considered.")
-      .setPossibleValues("1");
-
-    action.createParam(PARAM_WARNING)
-      .setDescription("Condition warning threshold")
-      .setExampleValue("5");
-
-    action.createParam(PARAM_ERROR)
-      .setDescription("Condition error threshold")
-      .setExampleValue("10");
-  }
-
-  static Long parseId(Request request, String paramName) {
-    try {
-      return Long.valueOf(request.mandatoryParam(paramName));
-    } catch (NumberFormatException badFormat) {
-      throw new BadRequestException(paramName + " must be a valid long value");
-    }
-  }
-
-  static JsonWriter writeQualityGate(QualityGateDto qualityGate, JsonWriter writer) {
-    return writer.beginObject()
-      .prop(PARAM_ID, qualityGate.getId())
-      .prop(PARAM_NAME, qualityGate.getName())
-      .endObject();
-  }
-
-  static JsonWriter writeQualityGateCondition(QualityGateConditionDto condition, JsonWriter writer) {
-    writer.beginObject()
-      .prop(PARAM_ID, condition.getId())
-      .prop(PARAM_METRIC, condition.getMetricKey())
-      .prop(PARAM_OPERATOR, condition.getOperator());
-    if (condition.getWarningThreshold() != null) {
-      writer.prop(PARAM_WARNING, condition.getWarningThreshold());
-    }
-    if (condition.getErrorThreshold() != null) {
-      writer.prop(PARAM_ERROR, condition.getErrorThreshold());
-    }
-    if (condition.getPeriod() != null) {
-      writer.prop(PARAM_PERIOD, condition.getPeriod());
-    }
-    writer.endObject();
-    return writer;
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWs.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWs.java
new file mode 100644 (file)
index 0000000..fc98402
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.qualitygate.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.db.qualitygate.QualityGateConditionDto;
+import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.server.exceptions.BadRequestException;
+
+public class QualityGatesWs implements WebService {
+
+  static final String PARAM_PAGE_SIZE = "pageSize";
+  static final String PARAM_PAGE = "page";
+  static final String PARAM_QUERY = "query";
+  static final String PARAM_NAME = "name";
+  static final String PARAM_ERROR = "error";
+  static final String PARAM_WARNING = "warning";
+  static final String PARAM_PERIOD = "period";
+  static final String PARAM_OPERATOR = "op";
+  static final String PARAM_METRIC = "metric";
+  static final String PARAM_GATE_ID = "gateId";
+  static final String PARAM_PROJECT_ID = "projectId";
+  static final String PARAM_ID = "id";
+
+  private final QualityGatesWsAction[] actions;
+
+  public QualityGatesWs(QualityGatesWsAction... actions) {
+    this.actions = actions;
+  }
+
+  @Override
+  public void define(Context context) {
+    NewController controller = context.createController("api/qualitygates")
+      .setSince("4.3")
+      .setDescription("Manage quality gates, including conditions and project association.");
+
+    for (QualityGatesWsAction action : actions) {
+      action.define(controller);
+    }
+
+    controller.done();
+  }
+
+  static void addConditionParams(NewAction action) {
+    action
+      .createParam(PARAM_METRIC)
+      .setDescription("Condition metric")
+      .setRequired(true)
+      .setExampleValue("blocker_violations");
+
+    action.createParam(PARAM_OPERATOR)
+      .setDescription("Condition operator:<br/>" +
+        "<ul>" +
+        "<li>EQ = equals</li>" +
+        "<li>NE = is not</li>" +
+        "<li>LT = is lower than</li>" +
+        "<li>GT = is greater than</li>" +
+        "</ui>")
+      .setExampleValue(QualityGateConditionDto.OPERATOR_EQUALS)
+      .setPossibleValues(QualityGateConditionDto.ALL_OPERATORS);
+
+    action.createParam(PARAM_PERIOD)
+      .setDescription("Condition period. If not set, the absolute value is considered.")
+      .setPossibleValues("1");
+
+    action.createParam(PARAM_WARNING)
+      .setDescription("Condition warning threshold")
+      .setExampleValue("5");
+
+    action.createParam(PARAM_ERROR)
+      .setDescription("Condition error threshold")
+      .setExampleValue("10");
+  }
+
+  static Long parseId(Request request, String paramName) {
+    try {
+      return Long.valueOf(request.mandatoryParam(paramName));
+    } catch (NumberFormatException badFormat) {
+      throw new BadRequestException(paramName + " must be a valid long value");
+    }
+  }
+
+  static JsonWriter writeQualityGate(QualityGateDto qualityGate, JsonWriter writer) {
+    return writer.beginObject()
+      .prop(PARAM_ID, qualityGate.getId())
+      .prop(PARAM_NAME, qualityGate.getName())
+      .endObject();
+  }
+
+  static JsonWriter writeQualityGateCondition(QualityGateConditionDto condition, JsonWriter writer) {
+    writer.beginObject()
+      .prop(PARAM_ID, condition.getId())
+      .prop(PARAM_METRIC, condition.getMetricKey())
+      .prop(PARAM_OPERATOR, condition.getOperator());
+    if (condition.getWarningThreshold() != null) {
+      writer.prop(PARAM_WARNING, condition.getWarningThreshold());
+    }
+    if (condition.getErrorThreshold() != null) {
+      writer.prop(PARAM_ERROR, condition.getErrorThreshold());
+    }
+    if (condition.getPeriod() != null) {
+      writer.prop(PARAM_PERIOD, condition.getPeriod());
+    }
+    writer.endObject();
+    return writer;
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsAction.java
new file mode 100644 (file)
index 0000000..a88a1d3
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.qualitygate.ws;
+
+import org.sonar.server.ws.WsAction;
+
+public interface QualityGatesWsAction extends WsAction {
+
+  // Marker interface
+}
index 51b807fd2ab3cd53c1c9d5e28ad561cc9b112aa9..ca685d7fb618ec8bb04fab0cb67ff10257fea669 100644 (file)
@@ -26,7 +26,7 @@ import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.db.qualitygate.QualityGateDto;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class RenameAction implements QGateWsAction {
+public class RenameAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
@@ -42,12 +42,12 @@ public class RenameAction implements QGateWsAction {
       .setPost(true)
       .setHandler(this);
 
-    action.createParam(QGatesWs.PARAM_ID)
+    action.createParam(QualityGatesWs.PARAM_ID)
       .setDescription("ID of the quality gate to rename")
       .setRequired(true)
       .setExampleValue("1");
 
-    action.createParam(QGatesWs.PARAM_NAME)
+    action.createParam(QualityGatesWs.PARAM_NAME)
       .setDescription("New name of the quality gate")
       .setRequired(true)
       .setExampleValue("My Quality Gate");
@@ -55,10 +55,10 @@ public class RenameAction implements QGateWsAction {
 
   @Override
   public void handle(Request request, Response response) {
-    long idToRename = QGatesWs.parseId(request, QGatesWs.PARAM_ID);
-    QualityGateDto renamedQualityGate = qualityGates.rename(idToRename, request.mandatoryParam(QGatesWs.PARAM_NAME));
+    long idToRename = QualityGatesWs.parseId(request, QualityGatesWs.PARAM_ID);
+    QualityGateDto renamedQualityGate = qualityGates.rename(idToRename, request.mandatoryParam(QualityGatesWs.PARAM_NAME));
     JsonWriter writer = response.newJsonWriter();
-    QGatesWs.writeQualityGate(renamedQualityGate, writer).close();
+    QualityGatesWs.writeQualityGate(renamedQualityGate, writer).close();
   }
 
 }
index a859ed87d0888a3a312d7d444209d50ea2d4491b..8f57e3bf59d4fdda02945451dad3415166a683ba 100644 (file)
@@ -29,7 +29,7 @@ import org.sonar.db.qualitygate.ProjectQgateAssociation;
 import org.sonar.db.qualitygate.ProjectQgateAssociationQuery;
 import org.sonar.server.qualitygate.QgateProjectFinder;
 
-public class SearchAction implements QGateWsAction {
+public class SearchAction implements QualityGatesWsAction {
 
   private final QgateProjectFinder projectFinder;
 
@@ -46,23 +46,23 @@ public class SearchAction implements QGateWsAction {
       .setResponseExample(Resources.getResource(this.getClass(), "example-search.json"))
       .setHandler(this);
 
-    action.createParam(QGatesWs.PARAM_GATE_ID)
+    action.createParam(QualityGatesWs.PARAM_GATE_ID)
       .setDescription("Quality Gate ID")
       .setRequired(true)
       .setExampleValue("1");
 
-    action.createParam(QGatesWs.PARAM_QUERY)
+    action.createParam(QualityGatesWs.PARAM_QUERY)
       .setDescription("To search for projects containing this string. If this parameter is set, \"selected\" is set to \"all\".")
       .setExampleValue("abc");
 
     action.addSelectionModeParam();
 
-    action.createParam(QGatesWs.PARAM_PAGE)
+    action.createParam(QualityGatesWs.PARAM_PAGE)
       .setDescription("Page number")
       .setDefaultValue("1")
       .setExampleValue("2");
 
-    action.createParam(QGatesWs.PARAM_PAGE_SIZE)
+    action.createParam(QualityGatesWs.PARAM_PAGE_SIZE)
       .setDescription("Page size")
       .setExampleValue("10");
   }
@@ -70,11 +70,11 @@ public class SearchAction implements QGateWsAction {
   @Override
   public void handle(Request request, Response response) {
     QgateProjectFinder.Association associations = projectFinder.find(ProjectQgateAssociationQuery.builder()
-      .gateId(request.mandatoryParam(QGatesWs.PARAM_GATE_ID))
-      .membership(request.param(QGatesWs.PARAM_QUERY) == null ? request.param(Param.SELECTED) : ProjectQgateAssociationQuery.ANY)
-      .projectSearch(request.param(QGatesWs.PARAM_QUERY))
-      .pageIndex(request.paramAsInt(QGatesWs.PARAM_PAGE))
-      .pageSize(request.paramAsInt(QGatesWs.PARAM_PAGE_SIZE))
+      .gateId(request.mandatoryParam(QualityGatesWs.PARAM_GATE_ID))
+      .membership(request.param(QualityGatesWs.PARAM_QUERY) == null ? request.param(Param.SELECTED) : ProjectQgateAssociationQuery.ANY)
+      .projectSearch(request.param(QualityGatesWs.PARAM_QUERY))
+      .pageIndex(request.paramAsInt(QualityGatesWs.PARAM_PAGE))
+      .pageSize(request.paramAsInt(QualityGatesWs.PARAM_PAGE_SIZE))
       .build());
     JsonWriter writer = response.newJsonWriter();
     writer.beginObject().prop("more", associations.hasMoreResults());
index 16aea9680de3d049eb378c44b46e592e87943e28..4afdc7ae8c586bb8dc7b62e732aaf8022cb0e91e 100644 (file)
@@ -24,7 +24,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class SelectAction implements QGateWsAction {
+public class SelectAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
@@ -40,12 +40,12 @@ public class SelectAction implements QGateWsAction {
       .setSince("4.3")
       .setHandler(this);
 
-    action.createParam(QGatesWs.PARAM_GATE_ID)
+    action.createParam(QualityGatesWs.PARAM_GATE_ID)
       .setDescription("Quality Gate ID")
       .setRequired(true)
       .setExampleValue("1");
 
-    action.createParam(QGatesWs.PARAM_PROJECT_ID)
+    action.createParam(QualityGatesWs.PARAM_PROJECT_ID)
       .setDescription("Project ID")
       .setRequired(true)
       .setExampleValue("12");
@@ -53,7 +53,7 @@ public class SelectAction implements QGateWsAction {
 
   @Override
   public void handle(Request request, Response response) {
-    qualityGates.associateProject(QGatesWs.parseId(request, QGatesWs.PARAM_GATE_ID), QGatesWs.parseId(request, QGatesWs.PARAM_PROJECT_ID));
+    qualityGates.associateProject(QualityGatesWs.parseId(request, QualityGatesWs.PARAM_GATE_ID), QualityGatesWs.parseId(request, QualityGatesWs.PARAM_PROJECT_ID));
     response.noContent();
   }
 
index 276b7a1c2e906531ad35f8bbe2b832c8eaef807a..38990131f9be654294fc7aa69721205e203b087e 100644 (file)
@@ -24,7 +24,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class SetAsDefaultAction implements QGateWsAction {
+public class SetAsDefaultAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
@@ -40,7 +40,7 @@ public class SetAsDefaultAction implements QGateWsAction {
       .setPost(true)
       .setHandler(this);
 
-    action.createParam(QGatesWs.PARAM_ID)
+    action.createParam(QualityGatesWs.PARAM_ID)
       .setDescription("ID of the quality gate to set as default")
       .setRequired(true)
       .setExampleValue("1");
@@ -48,7 +48,7 @@ public class SetAsDefaultAction implements QGateWsAction {
 
   @Override
   public void handle(Request request, Response response) {
-    qualityGates.setDefault(QGatesWs.parseId(request, QGatesWs.PARAM_ID));
+    qualityGates.setDefault(QualityGatesWs.parseId(request, QualityGatesWs.PARAM_ID));
     response.noContent();
   }
 
index fa05d172b8f286483c9edc7314838500fbdab1e7..cb447eb653c4ed4919ca6ba5d3fbfe62ff88ee26 100644 (file)
@@ -31,7 +31,7 @@ import org.sonar.db.qualitygate.QualityGateDto;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class ShowAction implements QGateWsAction {
+public class ShowAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
@@ -47,32 +47,32 @@ public class ShowAction implements QGateWsAction {
       .setResponseExample(Resources.getResource(this.getClass(), "example-show.json"))
       .setHandler(this);
 
-    action.createParam(QGatesWs.PARAM_ID)
+    action.createParam(QualityGatesWs.PARAM_ID)
       .setDescription("ID of the quality gate. Either id or name must be set")
       .setExampleValue("1");
 
-    action.createParam(QGatesWs.PARAM_NAME)
+    action.createParam(QualityGatesWs.PARAM_NAME)
       .setDescription("Name of the quality gate. Either id or name must be set")
       .setExampleValue("My Quality Gate");
   }
 
   @Override
   public void handle(Request request, Response response) {
-    Long qGateId = request.paramAsLong(QGatesWs.PARAM_ID);
-    String qGateName = request.param(QGatesWs.PARAM_NAME);
+    Long qGateId = request.paramAsLong(QualityGatesWs.PARAM_ID);
+    String qGateName = request.param(QualityGatesWs.PARAM_NAME);
     checkOneOfIdOrNamePresent(qGateId, qGateName);
 
     QualityGateDto qGate = qGateId == null ? qualityGates.get(qGateName) : qualityGates.get(qGateId);
     qGateId = qGate.getId();
 
     JsonWriter writer = response.newJsonWriter().beginObject()
-      .prop(QGatesWs.PARAM_ID, qGate.getId())
-      .prop(QGatesWs.PARAM_NAME, qGate.getName());
+      .prop(QualityGatesWs.PARAM_ID, qGate.getId())
+      .prop(QualityGatesWs.PARAM_NAME, qGate.getName());
     Collection<QualityGateConditionDto> conditions = qualityGates.listConditions(qGateId);
     if (!conditions.isEmpty()) {
       writer.name("conditions").beginArray();
       for (QualityGateConditionDto condition : conditions) {
-        QGatesWs.writeQualityGateCondition(condition, writer);
+        QualityGatesWs.writeQualityGateCondition(condition, writer);
       }
       writer.endArray();
     }
index 0747a23d64bd40057ea6026c13ec04dd6eb77075..29e905000ba1d49551ec33aeaaa066dc2afc3ec3 100644 (file)
@@ -24,7 +24,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class UnsetDefaultAction implements QGateWsAction {
+public class UnsetDefaultAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
@@ -40,7 +40,7 @@ public class UnsetDefaultAction implements QGateWsAction {
       .setPost(true)
       .setHandler(this);
 
-    action.createParam(QGatesWs.PARAM_ID)
+    action.createParam(QualityGatesWs.PARAM_ID)
       .setDescription("ID of the quality gate to unset as default")
       .setRequired(true)
       .setExampleValue("1");
index 16eb81dbc6df4102e67a10d177df9e1f59b043ff..111d68fc5ce95d14576d425da7e83203f98e7135 100644 (file)
@@ -24,7 +24,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.qualitygate.QualityGates;
 
-public class UpdateConditionAction implements QGateWsAction {
+public class UpdateConditionAction implements QualityGatesWsAction {
 
   private final QualityGates qualityGates;
 
@@ -41,24 +41,24 @@ public class UpdateConditionAction implements QGateWsAction {
       .setHandler(this);
 
     createCondition
-      .createParam(QGatesWs.PARAM_ID)
+      .createParam(QualityGatesWs.PARAM_ID)
       .setDescription("Condition ID")
       .setRequired(true)
       .setExampleValue("10");
 
-    QGatesWs.addConditionParams(createCondition);
+    QualityGatesWs.addConditionParams(createCondition);
   }
 
   @Override
   public void handle(Request request, Response response) {
-    QGatesWs.writeQualityGateCondition(
+    QualityGatesWs.writeQualityGateCondition(
       qualityGates.updateCondition(
-        QGatesWs.parseId(request, QGatesWs.PARAM_ID),
-        request.mandatoryParam(QGatesWs.PARAM_METRIC),
-        request.mandatoryParam(QGatesWs.PARAM_OPERATOR),
-        request.param(QGatesWs.PARAM_WARNING),
-        request.param(QGatesWs.PARAM_ERROR),
-        request.paramAsInt(QGatesWs.PARAM_PERIOD)
+        QualityGatesWs.parseId(request, QualityGatesWs.PARAM_ID),
+        request.mandatoryParam(QualityGatesWs.PARAM_METRIC),
+        request.mandatoryParam(QualityGatesWs.PARAM_OPERATOR),
+        request.param(QualityGatesWs.PARAM_WARNING),
+        request.param(QualityGatesWs.PARAM_ERROR),
+        request.paramAsInt(QualityGatesWs.PARAM_PERIOD)
         ), response.newJsonWriter()
       ).close();
   }
index cec59426d92ee9159da1e7deff446b0159859f90..70b98ba5878ae28d2777ab734c9e213bee26e8c7 100644 (file)
@@ -62,7 +62,7 @@ public class AppActionTest {
 
   @Before
   public void setUp() {
-    tester = new WsTester(new QGatesWs(
+    tester = new WsTester(new QualityGatesWs(
       new ListAction(qGates), new ShowAction(qGates), new SearchAction(mock(QgateProjectFinder.class)),
       new CreateAction(qGates), new CopyAction(qGates), new DestroyAction(qGates), new RenameAction(qGates),
       new SetAsDefaultAction(qGates), new UnsetDefaultAction(qGates),
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QGatesWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QGatesWsTest.java
deleted file mode 100644 (file)
index 39fb85d..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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.qualitygate.ws;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.server.ws.WebService.Action;
-import org.sonar.api.server.ws.WebService.Controller;
-import org.sonar.db.qualitygate.ProjectQgateAssociation;
-import org.sonar.db.qualitygate.ProjectQgateAssociationQuery;
-import org.sonar.db.qualitygate.QualityGateConditionDto;
-import org.sonar.db.qualitygate.QualityGateDto;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.qualitygate.QgateProjectFinder;
-import org.sonar.server.qualitygate.QgateProjectFinder.Association;
-import org.sonar.server.qualitygate.QualityGates;
-import org.sonar.server.ws.WsTester;
-
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-// TODO split testcases in action tests
-@RunWith(MockitoJUnitRunner.class)
-public class QGatesWsTest {
-
-  @Mock
-  private QualityGates qGates;
-
-  @Mock
-  private QgateProjectFinder projectFinder;
-
-  @Mock
-  private AppAction appHandler;
-
-  WsTester tester;
-
-  @Before
-  public void setUp() {
-    tester = new WsTester(new QGatesWs(
-      new ListAction(qGates), new ShowAction(qGates), new SearchAction(projectFinder),
-      new CreateAction(qGates), new CopyAction(qGates), new DestroyAction(qGates), new RenameAction(qGates),
-      new SetAsDefaultAction(qGates), new UnsetDefaultAction(qGates),
-      new CreateConditionAction(qGates), new UpdateConditionAction(qGates), new DeleteConditionAction(qGates),
-      new SelectAction(qGates), new DeselectAction(qGates), new AppAction(qGates)));
-  }
-
-  @Test
-  public void define_ws() {
-    Controller controller = tester.controller("api/qualitygates");
-    assertThat(controller).isNotNull();
-    assertThat(controller.path()).isEqualTo("api/qualitygates");
-    assertThat(controller.description()).isNotEmpty();
-    assertThat(controller.actions()).hasSize(15);
-
-    Action list = controller.action("list");
-    assertThat(list).isNotNull();
-    assertThat(list.handler()).isNotNull();
-    assertThat(list.since()).isEqualTo("4.3");
-    assertThat(list.isPost()).isFalse();
-    assertThat(list.isInternal()).isFalse();
-
-    Action show = controller.action("show");
-    assertThat(show).isNotNull();
-    assertThat(show.handler()).isNotNull();
-    assertThat(show.since()).isEqualTo("4.3");
-    assertThat(show.isPost()).isFalse();
-    assertThat(show.param("id")).isNotNull();
-    assertThat(show.isInternal()).isFalse();
-
-    Action create = controller.action("create");
-    assertThat(create).isNotNull();
-    assertThat(create.handler()).isNotNull();
-    assertThat(create.since()).isEqualTo("4.3");
-    assertThat(create.isPost()).isTrue();
-    assertThat(create.param("name")).isNotNull();
-    assertThat(create.isInternal()).isFalse();
-
-    Action copy = controller.action("copy");
-    assertThat(copy).isNotNull();
-    assertThat(copy.handler()).isNotNull();
-    assertThat(copy.since()).isEqualTo("4.3");
-    assertThat(copy.isPost()).isTrue();
-    assertThat(copy.param("id")).isNotNull();
-    assertThat(copy.param("name")).isNotNull();
-    assertThat(copy.isInternal()).isFalse();
-
-    Action destroy = controller.action("destroy");
-    assertThat(destroy).isNotNull();
-    assertThat(destroy.handler()).isNotNull();
-    assertThat(destroy.since()).isEqualTo("4.3");
-    assertThat(destroy.isPost()).isTrue();
-    assertThat(destroy.param("id")).isNotNull();
-    assertThat(destroy.isInternal()).isFalse();
-
-    Action rename = controller.action("rename");
-    assertThat(rename).isNotNull();
-    assertThat(rename.handler()).isNotNull();
-    assertThat(rename.since()).isEqualTo("4.3");
-    assertThat(rename.isPost()).isTrue();
-    assertThat(rename.param("id")).isNotNull();
-    assertThat(rename.param("name")).isNotNull();
-    assertThat(rename.isInternal()).isFalse();
-
-    Action setDefault = controller.action("set_as_default");
-    assertThat(setDefault).isNotNull();
-    assertThat(setDefault.handler()).isNotNull();
-    assertThat(setDefault.since()).isEqualTo("4.3");
-    assertThat(setDefault.isPost()).isTrue();
-    assertThat(setDefault.param("id")).isNotNull();
-    assertThat(setDefault.isInternal()).isFalse();
-
-    Action unsetDefault = controller.action("unset_default");
-    assertThat(unsetDefault).isNotNull();
-    assertThat(unsetDefault.handler()).isNotNull();
-    assertThat(unsetDefault.since()).isEqualTo("4.3");
-    assertThat(unsetDefault.isPost()).isTrue();
-    assertThat(unsetDefault.isInternal()).isFalse();
-
-    Action createCondition = controller.action("create_condition");
-    assertThat(createCondition).isNotNull();
-    assertThat(createCondition.handler()).isNotNull();
-    assertThat(createCondition.since()).isEqualTo("4.3");
-    assertThat(createCondition.isPost()).isTrue();
-    assertThat(createCondition.param("gateId")).isNotNull();
-    assertThat(createCondition.param("metric")).isNotNull();
-    assertThat(createCondition.param("op")).isNotNull();
-    assertThat(createCondition.param("warning")).isNotNull();
-    assertThat(createCondition.param("error")).isNotNull();
-    assertThat(createCondition.param("period")).isNotNull();
-    assertThat(createCondition.isInternal()).isFalse();
-
-    Action updateCondition = controller.action("update_condition");
-    assertThat(updateCondition).isNotNull();
-    assertThat(updateCondition.handler()).isNotNull();
-    assertThat(updateCondition.since()).isEqualTo("4.3");
-    assertThat(updateCondition.isPost()).isTrue();
-    assertThat(updateCondition.param("id")).isNotNull();
-    assertThat(updateCondition.param("metric")).isNotNull();
-    assertThat(updateCondition.param("op")).isNotNull();
-    assertThat(updateCondition.param("warning")).isNotNull();
-    assertThat(updateCondition.param("error")).isNotNull();
-    assertThat(updateCondition.param("period")).isNotNull();
-    assertThat(updateCondition.isInternal()).isFalse();
-
-    Action deleteCondition = controller.action("delete_condition");
-    assertThat(deleteCondition).isNotNull();
-    assertThat(deleteCondition.handler()).isNotNull();
-    assertThat(deleteCondition.since()).isEqualTo("4.3");
-    assertThat(deleteCondition.isPost()).isTrue();
-    assertThat(deleteCondition.param("id")).isNotNull();
-    assertThat(deleteCondition.isInternal()).isFalse();
-
-    Action appInit = controller.action("app");
-    assertThat(appInit.isInternal()).isTrue();
-  }
-
-  @Test
-  public void create_nominal() throws Exception {
-    String name = "New QG";
-    when(qGates.create(name)).thenReturn(new QualityGateDto().setId(42L).setName(name));
-    tester.newPostRequest("api/qualitygates", "create").setParam("name", name).execute()
-      .assertJson("{\"id\":42,\"name\":\"New QG\"}");
-  }
-
-  @Test
-  public void copy_nominal() throws Exception {
-    String name = "Copied QG";
-    when(qGates.copy(24L, name)).thenReturn(new QualityGateDto().setId(42L).setName(name));
-    tester.newPostRequest("api/qualitygates", "copy").setParam("id", "24").setParam("name", name).execute()
-      .assertJson("{\"id\":42,\"name\":\"Copied QG\"}");
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void create_with_missing_name() throws Exception {
-    tester.newPostRequest("api/qualitygates", "create").execute();
-  }
-
-  @Test(expected = BadRequestException.class)
-  public void create_with_duplicate_name() throws Exception {
-    String name = "New QG";
-    when(qGates.create(name)).thenThrow(new BadRequestException("Name is already used"));
-    tester.newPostRequest("api/qualitygates", "create").setParam("name", name).execute();
-  }
-
-  @Test
-  public void rename_nominal() throws Exception {
-    Long id = 42L;
-    String name = "New QG";
-    when(qGates.rename(id, name)).thenReturn(new QualityGateDto().setId(id).setName(name));
-    tester.newPostRequest("api/qualitygates", "rename").setParam("id", id.toString()).setParam("name", name).execute()
-      .assertJson("{\"id\":42,\"name\":\"New QG\"}");
-    ;
-  }
-
-  @Test
-  public void set_as_default_nominal() throws Exception {
-    Long id = 42L;
-    tester.newPostRequest("api/qualitygates", "set_as_default").setParam("id", id.toString()).execute()
-      .assertNoContent();
-    verify(qGates).setDefault(id);
-  }
-
-  @Test
-  public void unset_default_nominal() throws Exception {
-    tester.newPostRequest("api/qualitygates", "unset_default").execute()
-      .assertNoContent();
-    verify(qGates).setDefault(null);
-  }
-
-  @Test
-  public void destroy_nominal() throws Exception {
-    Long id = 42L;
-    tester.newPostRequest("api/qualitygates", "destroy").setParam("id", id.toString()).execute()
-      .assertNoContent();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void destroy_without_id() throws Exception {
-    tester.newPostRequest("api/qualitygates", "destroy").execute();
-  }
-
-  @Test(expected = BadRequestException.class)
-  public void destroy_with_invalid_id() throws Exception {
-    tester.newPostRequest("api/qualitygates", "destroy").setParam("id", "polop").execute();
-  }
-
-  @Test
-  public void list_nominal() throws Exception {
-    when(qGates.list()).thenReturn(Lists.newArrayList(
-      new QualityGateDto().setId(42L).setName("Golden"),
-      new QualityGateDto().setId(43L).setName("Star"),
-      new QualityGateDto().setId(666L).setName("Ninth")
-      ));
-    when(qGates.currentUserHasWritePermission()).thenReturn(false);
-    tester.newGetRequest("api/qualitygates", "list").execute().assertJson(
-      "{\"qualitygates\":[{\"id\":42,\"name\":\"Golden\"},{\"id\":43,\"name\":\"Star\"},{\"id\":666,\"name\":\"Ninth\"}]}");
-  }
-
-  @Test
-  public void list_with_default() throws Exception {
-    QualityGateDto defaultQgate = new QualityGateDto().setId(42L).setName("Golden");
-    when(qGates.list()).thenReturn(Lists.newArrayList(
-      defaultQgate,
-      new QualityGateDto().setId(43L).setName("Star"),
-      new QualityGateDto().setId(666L).setName("Ninth")
-      ));
-    when(qGates.getDefault()).thenReturn(defaultQgate);
-    tester.newGetRequest("api/qualitygates", "list").execute().assertJson(
-      "{\"qualitygates\":[{\"id\":42,\"name\":\"Golden\"},{\"id\":43,\"name\":\"Star\"},{\"id\":666,\"name\":\"Ninth\"}],\"default\":42}");
-  }
-
-  @Test
-  public void show_empty() throws Exception {
-    long gateId = 12345L;
-    when(qGates.get(gateId)).thenReturn(new QualityGateDto().setId(gateId).setName("Golden"));
-    tester.newGetRequest("api/qualitygates", "show").setParam("id", Long.toString(gateId)).execute().assertJson(
-      "{\"id\":12345,\"name\":\"Golden\"}");
-  }
-
-  @Test
-  public void show_by_id_nominal() throws Exception {
-    long gateId = 12345L;
-    when(qGates.get(gateId)).thenReturn(new QualityGateDto().setId(gateId).setName("Golden"));
-    when(qGates.listConditions(gateId)).thenReturn(ImmutableList.of(
-      new QualityGateConditionDto().setId(1L).setMetricKey("ncloc").setOperator("GT").setErrorThreshold("10000"),
-      new QualityGateConditionDto().setId(2L).setMetricKey("new_coverage").setOperator("LT").setWarningThreshold("90").setPeriod(3)
-      ));
-    tester.newGetRequest("api/qualitygates", "show").setParam("id", Long.toString(gateId)).execute().assertJson(
-      "{\"id\":12345,\"name\":\"Golden\",\"conditions\":["
-        + "{\"id\":1,\"metric\":\"ncloc\",\"op\":\"GT\",\"error\":\"10000\"},"
-        + "{\"id\":2,\"metric\":\"new_coverage\",\"op\":\"LT\",\"warning\":\"90\",\"period\":3}"
-        + "]}"
-      );
-  }
-
-  @Test
-  public void show_by_name_nominal() throws Exception {
-    long qGateId = 12345L;
-    String gateName = "Golden";
-    when(qGates.get(gateName)).thenReturn(new QualityGateDto().setId(qGateId).setName(gateName));
-    when(qGates.listConditions(qGateId)).thenReturn(ImmutableList.of(
-      new QualityGateConditionDto().setId(1L).setMetricKey("ncloc").setOperator("GT").setErrorThreshold("10000"),
-      new QualityGateConditionDto().setId(2L).setMetricKey("new_coverage").setOperator("LT").setWarningThreshold("90").setPeriod(3)
-      ));
-    tester.newGetRequest("api/qualitygates", "show").setParam("name", gateName).execute().assertJson(
-      "{\"id\":12345,\"name\":\"Golden\",\"conditions\":["
-        + "{\"id\":1,\"metric\":\"ncloc\",\"op\":\"GT\",\"error\":\"10000\"},"
-        + "{\"id\":2,\"metric\":\"new_coverage\",\"op\":\"LT\",\"warning\":\"90\",\"period\":3}"
-        + "]}"
-      );
-  }
-
-  @Test(expected = BadRequestException.class)
-  public void show_without_parameters() throws Exception {
-    tester.newGetRequest("api/qualitygates", "show").execute();
-  }
-
-  @Test(expected = BadRequestException.class)
-  public void show_with_both_parameters() throws Exception {
-    tester.newGetRequest("api/qualitygates", "show").setParam("id", "12345").setParam("name", "Polop").execute();
-  }
-
-  @Test
-  public void create_condition_nominal() throws Exception {
-    long qGateId = 42L;
-    String metricKey = "coverage";
-    String operator = "LT";
-    String warningThreshold = "80";
-    String errorThreshold = "75";
-    when(qGates.createCondition(qGateId, metricKey, operator, warningThreshold, errorThreshold, null))
-      .thenReturn(new QualityGateConditionDto().setId(12345L).setQualityGateId(qGateId).setMetricId(10).setMetricKey(metricKey)
-        .setOperator(operator).setWarningThreshold(warningThreshold).setErrorThreshold(errorThreshold));
-    tester.newPostRequest("api/qualitygates", "create_condition")
-      .setParam("gateId", Long.toString(qGateId))
-      .setParam("metric", metricKey)
-      .setParam("op", operator)
-      .setParam("warning", warningThreshold)
-      .setParam("error", errorThreshold)
-      .execute()
-      .assertJson("{\"id\":12345,\"metric\":\"coverage\",\"op\":\"LT\",\"warning\":\"80\",\"error\":\"75\"}");
-  }
-
-  @Test
-  public void update_condition_nominal() throws Exception {
-    long condId = 12345L;
-    String metricKey = "coverage";
-    String operator = "LT";
-    String warningThreshold = "80";
-    String errorThreshold = "75";
-    when(qGates.updateCondition(condId, metricKey, operator, warningThreshold, errorThreshold, null))
-      .thenReturn(new QualityGateConditionDto().setId(condId).setMetricId(10).setMetricKey(metricKey)
-        .setOperator(operator).setWarningThreshold(warningThreshold).setErrorThreshold(errorThreshold));
-    tester.newPostRequest("api/qualitygates", "update_condition")
-      .setParam("id", Long.toString(condId))
-      .setParam("metric", metricKey)
-      .setParam("op", operator)
-      .setParam("warning", warningThreshold)
-      .setParam("error", errorThreshold)
-      .execute()
-      .assertJson("{\"id\":12345,\"metric\":\"coverage\",\"op\":\"LT\",\"warning\":\"80\",\"error\":\"75\"}");
-  }
-
-  @Test
-  public void delete_condition_nominal() throws Exception {
-    long condId = 12345L;
-    tester.newPostRequest("api/qualitygates", "delete_condition")
-      .setParam("id", Long.toString(condId))
-      .execute()
-      .assertNoContent();
-  }
-
-  @Test
-  public void search_with_query() throws Exception {
-    long gateId = 12345L;
-    Association assoc = mock(Association.class);
-    when(assoc.hasMoreResults()).thenReturn(true);
-    List<ProjectQgateAssociation> projects = ImmutableList.of(
-      new ProjectQgateAssociation().setId(42L).setName("Project One").setMember(false),
-      new ProjectQgateAssociation().setId(24L).setName("Project Two").setMember(true)
-      );
-    when(assoc.projects()).thenReturn(projects);
-    when(projectFinder.find(any(ProjectQgateAssociationQuery.class))).thenReturn(assoc);
-
-    tester.newGetRequest("api/qualitygates", "search")
-      .setParam("gateId", Long.toString(gateId))
-      .setParam("query", "Project")
-      .execute()
-      .assertJson("{\"more\":true,\"results\":["
-        + "{\"id\":42,\"name\":\"Project One\",\"selected\":false},"
-        + "{\"id\":24,\"name\":\"Project Two\",\"selected\":true}"
-        + "]}");
-    ArgumentCaptor<ProjectQgateAssociationQuery> queryCaptor = ArgumentCaptor.forClass(ProjectQgateAssociationQuery.class);
-    verify(projectFinder).find(queryCaptor.capture());
-    ProjectQgateAssociationQuery query = queryCaptor.getValue();
-    assertThat(query.membership()).isEqualTo(ProjectQgateAssociationQuery.ANY);
-  }
-
-  @Test
-  public void search_nominal() throws Exception {
-    long gateId = 12345L;
-    Association assoc = mock(Association.class);
-    when(assoc.hasMoreResults()).thenReturn(true);
-    List<ProjectQgateAssociation> projects = ImmutableList.of(
-      new ProjectQgateAssociation().setId(24L).setName("Project Two").setMember(true)
-      );
-    when(assoc.projects()).thenReturn(projects);
-    when(projectFinder.find(any(ProjectQgateAssociationQuery.class))).thenReturn(assoc);
-
-    tester.newGetRequest("api/qualitygates", "search")
-      .setParam("gateId", Long.toString(gateId))
-      .execute()
-      .assertJson("{\"more\":true,\"results\":["
-        + "{\"id\":24,\"name\":\"Project Two\",\"selected\":true}"
-        + "]}");
-    ArgumentCaptor<ProjectQgateAssociationQuery> queryCaptor = ArgumentCaptor.forClass(ProjectQgateAssociationQuery.class);
-    verify(projectFinder).find(queryCaptor.capture());
-    ProjectQgateAssociationQuery query = queryCaptor.getValue();
-    assertThat(query.membership()).isEqualTo(ProjectQgateAssociationQuery.IN);
-  }
-
-  @Test
-  public void select_nominal() throws Exception {
-    long gateId = 42L;
-    long projectId = 666L;
-    tester.newPostRequest("api/qualitygates", "select")
-      .setParam("gateId", Long.toString(gateId))
-      .setParam("projectId", Long.toString(projectId))
-      .execute()
-      .assertNoContent();
-    verify(qGates).associateProject(gateId, projectId);
-  }
-
-  @Test
-  public void deselect_nominal() throws Exception {
-    long gateId = 42L;
-    long projectId = 666L;
-    tester.newPostRequest("api/qualitygates", "deselect")
-      .setParam("gateId", Long.toString(gateId))
-      .setParam("projectId", Long.toString(projectId))
-      .execute()
-      .assertNoContent();
-    verify(qGates).dissociateProject(gateId, projectId);
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java
new file mode 100644 (file)
index 0000000..7ae85a1
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.qualitygate.ws;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.server.ws.WebService.Action;
+import org.sonar.api.server.ws.WebService.Controller;
+import org.sonar.db.qualitygate.ProjectQgateAssociation;
+import org.sonar.db.qualitygate.ProjectQgateAssociationQuery;
+import org.sonar.db.qualitygate.QualityGateConditionDto;
+import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.qualitygate.QgateProjectFinder;
+import org.sonar.server.qualitygate.QgateProjectFinder.Association;
+import org.sonar.server.qualitygate.QualityGates;
+import org.sonar.server.ws.WsTester;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+// TODO split testcases in action tests
+@RunWith(MockitoJUnitRunner.class)
+public class QualityGatesWsTest {
+
+  @Mock
+  private QualityGates qGates;
+
+  @Mock
+  private QgateProjectFinder projectFinder;
+
+  @Mock
+  private AppAction appHandler;
+
+  WsTester tester;
+
+  @Before
+  public void setUp() {
+    tester = new WsTester(new QualityGatesWs(
+      new ListAction(qGates), new ShowAction(qGates), new SearchAction(projectFinder),
+      new CreateAction(qGates), new CopyAction(qGates), new DestroyAction(qGates), new RenameAction(qGates),
+      new SetAsDefaultAction(qGates), new UnsetDefaultAction(qGates),
+      new CreateConditionAction(qGates), new UpdateConditionAction(qGates), new DeleteConditionAction(qGates),
+      new SelectAction(qGates), new DeselectAction(qGates), new AppAction(qGates)));
+  }
+
+  @Test
+  public void define_ws() {
+    Controller controller = tester.controller("api/qualitygates");
+    assertThat(controller).isNotNull();
+    assertThat(controller.path()).isEqualTo("api/qualitygates");
+    assertThat(controller.description()).isNotEmpty();
+    assertThat(controller.actions()).hasSize(15);
+
+    Action list = controller.action("list");
+    assertThat(list).isNotNull();
+    assertThat(list.handler()).isNotNull();
+    assertThat(list.since()).isEqualTo("4.3");
+    assertThat(list.isPost()).isFalse();
+    assertThat(list.isInternal()).isFalse();
+
+    Action show = controller.action("show");
+    assertThat(show).isNotNull();
+    assertThat(show.handler()).isNotNull();
+    assertThat(show.since()).isEqualTo("4.3");
+    assertThat(show.isPost()).isFalse();
+    assertThat(show.param("id")).isNotNull();
+    assertThat(show.isInternal()).isFalse();
+
+    Action create = controller.action("create");
+    assertThat(create).isNotNull();
+    assertThat(create.handler()).isNotNull();
+    assertThat(create.since()).isEqualTo("4.3");
+    assertThat(create.isPost()).isTrue();
+    assertThat(create.param("name")).isNotNull();
+    assertThat(create.isInternal()).isFalse();
+
+    Action copy = controller.action("copy");
+    assertThat(copy).isNotNull();
+    assertThat(copy.handler()).isNotNull();
+    assertThat(copy.since()).isEqualTo("4.3");
+    assertThat(copy.isPost()).isTrue();
+    assertThat(copy.param("id")).isNotNull();
+    assertThat(copy.param("name")).isNotNull();
+    assertThat(copy.isInternal()).isFalse();
+
+    Action destroy = controller.action("destroy");
+    assertThat(destroy).isNotNull();
+    assertThat(destroy.handler()).isNotNull();
+    assertThat(destroy.since()).isEqualTo("4.3");
+    assertThat(destroy.isPost()).isTrue();
+    assertThat(destroy.param("id")).isNotNull();
+    assertThat(destroy.isInternal()).isFalse();
+
+    Action rename = controller.action("rename");
+    assertThat(rename).isNotNull();
+    assertThat(rename.handler()).isNotNull();
+    assertThat(rename.since()).isEqualTo("4.3");
+    assertThat(rename.isPost()).isTrue();
+    assertThat(rename.param("id")).isNotNull();
+    assertThat(rename.param("name")).isNotNull();
+    assertThat(rename.isInternal()).isFalse();
+
+    Action setDefault = controller.action("set_as_default");
+    assertThat(setDefault).isNotNull();
+    assertThat(setDefault.handler()).isNotNull();
+    assertThat(setDefault.since()).isEqualTo("4.3");
+    assertThat(setDefault.isPost()).isTrue();
+    assertThat(setDefault.param("id")).isNotNull();
+    assertThat(setDefault.isInternal()).isFalse();
+
+    Action unsetDefault = controller.action("unset_default");
+    assertThat(unsetDefault).isNotNull();
+    assertThat(unsetDefault.handler()).isNotNull();
+    assertThat(unsetDefault.since()).isEqualTo("4.3");
+    assertThat(unsetDefault.isPost()).isTrue();
+    assertThat(unsetDefault.isInternal()).isFalse();
+
+    Action createCondition = controller.action("create_condition");
+    assertThat(createCondition).isNotNull();
+    assertThat(createCondition.handler()).isNotNull();
+    assertThat(createCondition.since()).isEqualTo("4.3");
+    assertThat(createCondition.isPost()).isTrue();
+    assertThat(createCondition.param("gateId")).isNotNull();
+    assertThat(createCondition.param("metric")).isNotNull();
+    assertThat(createCondition.param("op")).isNotNull();
+    assertThat(createCondition.param("warning")).isNotNull();
+    assertThat(createCondition.param("error")).isNotNull();
+    assertThat(createCondition.param("period")).isNotNull();
+    assertThat(createCondition.isInternal()).isFalse();
+
+    Action updateCondition = controller.action("update_condition");
+    assertThat(updateCondition).isNotNull();
+    assertThat(updateCondition.handler()).isNotNull();
+    assertThat(updateCondition.since()).isEqualTo("4.3");
+    assertThat(updateCondition.isPost()).isTrue();
+    assertThat(updateCondition.param("id")).isNotNull();
+    assertThat(updateCondition.param("metric")).isNotNull();
+    assertThat(updateCondition.param("op")).isNotNull();
+    assertThat(updateCondition.param("warning")).isNotNull();
+    assertThat(updateCondition.param("error")).isNotNull();
+    assertThat(updateCondition.param("period")).isNotNull();
+    assertThat(updateCondition.isInternal()).isFalse();
+
+    Action deleteCondition = controller.action("delete_condition");
+    assertThat(deleteCondition).isNotNull();
+    assertThat(deleteCondition.handler()).isNotNull();
+    assertThat(deleteCondition.since()).isEqualTo("4.3");
+    assertThat(deleteCondition.isPost()).isTrue();
+    assertThat(deleteCondition.param("id")).isNotNull();
+    assertThat(deleteCondition.isInternal()).isFalse();
+
+    Action appInit = controller.action("app");
+    assertThat(appInit.isInternal()).isTrue();
+  }
+
+  @Test
+  public void create_nominal() throws Exception {
+    String name = "New QG";
+    when(qGates.create(name)).thenReturn(new QualityGateDto().setId(42L).setName(name));
+    tester.newPostRequest("api/qualitygates", "create").setParam("name", name).execute()
+      .assertJson("{\"id\":42,\"name\":\"New QG\"}");
+  }
+
+  @Test
+  public void copy_nominal() throws Exception {
+    String name = "Copied QG";
+    when(qGates.copy(24L, name)).thenReturn(new QualityGateDto().setId(42L).setName(name));
+    tester.newPostRequest("api/qualitygates", "copy").setParam("id", "24").setParam("name", name).execute()
+      .assertJson("{\"id\":42,\"name\":\"Copied QG\"}");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void create_with_missing_name() throws Exception {
+    tester.newPostRequest("api/qualitygates", "create").execute();
+  }
+
+  @Test(expected = BadRequestException.class)
+  public void create_with_duplicate_name() throws Exception {
+    String name = "New QG";
+    when(qGates.create(name)).thenThrow(new BadRequestException("Name is already used"));
+    tester.newPostRequest("api/qualitygates", "create").setParam("name", name).execute();
+  }
+
+  @Test
+  public void rename_nominal() throws Exception {
+    Long id = 42L;
+    String name = "New QG";
+    when(qGates.rename(id, name)).thenReturn(new QualityGateDto().setId(id).setName(name));
+    tester.newPostRequest("api/qualitygates", "rename").setParam("id", id.toString()).setParam("name", name).execute()
+      .assertJson("{\"id\":42,\"name\":\"New QG\"}");
+    ;
+  }
+
+  @Test
+  public void set_as_default_nominal() throws Exception {
+    Long id = 42L;
+    tester.newPostRequest("api/qualitygates", "set_as_default").setParam("id", id.toString()).execute()
+      .assertNoContent();
+    verify(qGates).setDefault(id);
+  }
+
+  @Test
+  public void unset_default_nominal() throws Exception {
+    tester.newPostRequest("api/qualitygates", "unset_default").execute()
+      .assertNoContent();
+    verify(qGates).setDefault(null);
+  }
+
+  @Test
+  public void destroy_nominal() throws Exception {
+    Long id = 42L;
+    tester.newPostRequest("api/qualitygates", "destroy").setParam("id", id.toString()).execute()
+      .assertNoContent();
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void destroy_without_id() throws Exception {
+    tester.newPostRequest("api/qualitygates", "destroy").execute();
+  }
+
+  @Test(expected = BadRequestException.class)
+  public void destroy_with_invalid_id() throws Exception {
+    tester.newPostRequest("api/qualitygates", "destroy").setParam("id", "polop").execute();
+  }
+
+  @Test
+  public void list_nominal() throws Exception {
+    when(qGates.list()).thenReturn(Lists.newArrayList(
+      new QualityGateDto().setId(42L).setName("Golden"),
+      new QualityGateDto().setId(43L).setName("Star"),
+      new QualityGateDto().setId(666L).setName("Ninth")
+      ));
+    when(qGates.currentUserHasWritePermission()).thenReturn(false);
+    tester.newGetRequest("api/qualitygates", "list").execute().assertJson(
+      "{\"qualitygates\":[{\"id\":42,\"name\":\"Golden\"},{\"id\":43,\"name\":\"Star\"},{\"id\":666,\"name\":\"Ninth\"}]}");
+  }
+
+  @Test
+  public void list_with_default() throws Exception {
+    QualityGateDto defaultQgate = new QualityGateDto().setId(42L).setName("Golden");
+    when(qGates.list()).thenReturn(Lists.newArrayList(
+      defaultQgate,
+      new QualityGateDto().setId(43L).setName("Star"),
+      new QualityGateDto().setId(666L).setName("Ninth")
+      ));
+    when(qGates.getDefault()).thenReturn(defaultQgate);
+    tester.newGetRequest("api/qualitygates", "list").execute().assertJson(
+      "{\"qualitygates\":[{\"id\":42,\"name\":\"Golden\"},{\"id\":43,\"name\":\"Star\"},{\"id\":666,\"name\":\"Ninth\"}],\"default\":42}");
+  }
+
+  @Test
+  public void show_empty() throws Exception {
+    long gateId = 12345L;
+    when(qGates.get(gateId)).thenReturn(new QualityGateDto().setId(gateId).setName("Golden"));
+    tester.newGetRequest("api/qualitygates", "show").setParam("id", Long.toString(gateId)).execute().assertJson(
+      "{\"id\":12345,\"name\":\"Golden\"}");
+  }
+
+  @Test
+  public void show_by_id_nominal() throws Exception {
+    long gateId = 12345L;
+    when(qGates.get(gateId)).thenReturn(new QualityGateDto().setId(gateId).setName("Golden"));
+    when(qGates.listConditions(gateId)).thenReturn(ImmutableList.of(
+      new QualityGateConditionDto().setId(1L).setMetricKey("ncloc").setOperator("GT").setErrorThreshold("10000"),
+      new QualityGateConditionDto().setId(2L).setMetricKey("new_coverage").setOperator("LT").setWarningThreshold("90").setPeriod(3)
+      ));
+    tester.newGetRequest("api/qualitygates", "show").setParam("id", Long.toString(gateId)).execute().assertJson(
+      "{\"id\":12345,\"name\":\"Golden\",\"conditions\":["
+        + "{\"id\":1,\"metric\":\"ncloc\",\"op\":\"GT\",\"error\":\"10000\"},"
+        + "{\"id\":2,\"metric\":\"new_coverage\",\"op\":\"LT\",\"warning\":\"90\",\"period\":3}"
+        + "]}"
+      );
+  }
+
+  @Test
+  public void show_by_name_nominal() throws Exception {
+    long qGateId = 12345L;
+    String gateName = "Golden";
+    when(qGates.get(gateName)).thenReturn(new QualityGateDto().setId(qGateId).setName(gateName));
+    when(qGates.listConditions(qGateId)).thenReturn(ImmutableList.of(
+      new QualityGateConditionDto().setId(1L).setMetricKey("ncloc").setOperator("GT").setErrorThreshold("10000"),
+      new QualityGateConditionDto().setId(2L).setMetricKey("new_coverage").setOperator("LT").setWarningThreshold("90").setPeriod(3)
+      ));
+    tester.newGetRequest("api/qualitygates", "show").setParam("name", gateName).execute().assertJson(
+      "{\"id\":12345,\"name\":\"Golden\",\"conditions\":["
+        + "{\"id\":1,\"metric\":\"ncloc\",\"op\":\"GT\",\"error\":\"10000\"},"
+        + "{\"id\":2,\"metric\":\"new_coverage\",\"op\":\"LT\",\"warning\":\"90\",\"period\":3}"
+        + "]}"
+      );
+  }
+
+  @Test(expected = BadRequestException.class)
+  public void show_without_parameters() throws Exception {
+    tester.newGetRequest("api/qualitygates", "show").execute();
+  }
+
+  @Test(expected = BadRequestException.class)
+  public void show_with_both_parameters() throws Exception {
+    tester.newGetRequest("api/qualitygates", "show").setParam("id", "12345").setParam("name", "Polop").execute();
+  }
+
+  @Test
+  public void create_condition_nominal() throws Exception {
+    long qGateId = 42L;
+    String metricKey = "coverage";
+    String operator = "LT";
+    String warningThreshold = "80";
+    String errorThreshold = "75";
+    when(qGates.createCondition(qGateId, metricKey, operator, warningThreshold, errorThreshold, null))
+      .thenReturn(new QualityGateConditionDto().setId(12345L).setQualityGateId(qGateId).setMetricId(10).setMetricKey(metricKey)
+        .setOperator(operator).setWarningThreshold(warningThreshold).setErrorThreshold(errorThreshold));
+    tester.newPostRequest("api/qualitygates", "create_condition")
+      .setParam("gateId", Long.toString(qGateId))
+      .setParam("metric", metricKey)
+      .setParam("op", operator)
+      .setParam("warning", warningThreshold)
+      .setParam("error", errorThreshold)
+      .execute()
+      .assertJson("{\"id\":12345,\"metric\":\"coverage\",\"op\":\"LT\",\"warning\":\"80\",\"error\":\"75\"}");
+  }
+
+  @Test
+  public void update_condition_nominal() throws Exception {
+    long condId = 12345L;
+    String metricKey = "coverage";
+    String operator = "LT";
+    String warningThreshold = "80";
+    String errorThreshold = "75";
+    when(qGates.updateCondition(condId, metricKey, operator, warningThreshold, errorThreshold, null))
+      .thenReturn(new QualityGateConditionDto().setId(condId).setMetricId(10).setMetricKey(metricKey)
+        .setOperator(operator).setWarningThreshold(warningThreshold).setErrorThreshold(errorThreshold));
+    tester.newPostRequest("api/qualitygates", "update_condition")
+      .setParam("id", Long.toString(condId))
+      .setParam("metric", metricKey)
+      .setParam("op", operator)
+      .setParam("warning", warningThreshold)
+      .setParam("error", errorThreshold)
+      .execute()
+      .assertJson("{\"id\":12345,\"metric\":\"coverage\",\"op\":\"LT\",\"warning\":\"80\",\"error\":\"75\"}");
+  }
+
+  @Test
+  public void delete_condition_nominal() throws Exception {
+    long condId = 12345L;
+    tester.newPostRequest("api/qualitygates", "delete_condition")
+      .setParam("id", Long.toString(condId))
+      .execute()
+      .assertNoContent();
+  }
+
+  @Test
+  public void search_with_query() throws Exception {
+    long gateId = 12345L;
+    Association assoc = mock(Association.class);
+    when(assoc.hasMoreResults()).thenReturn(true);
+    List<ProjectQgateAssociation> projects = ImmutableList.of(
+      new ProjectQgateAssociation().setId(42L).setName("Project One").setMember(false),
+      new ProjectQgateAssociation().setId(24L).setName("Project Two").setMember(true)
+      );
+    when(assoc.projects()).thenReturn(projects);
+    when(projectFinder.find(any(ProjectQgateAssociationQuery.class))).thenReturn(assoc);
+
+    tester.newGetRequest("api/qualitygates", "search")
+      .setParam("gateId", Long.toString(gateId))
+      .setParam("query", "Project")
+      .execute()
+      .assertJson("{\"more\":true,\"results\":["
+        + "{\"id\":42,\"name\":\"Project One\",\"selected\":false},"
+        + "{\"id\":24,\"name\":\"Project Two\",\"selected\":true}"
+        + "]}");
+    ArgumentCaptor<ProjectQgateAssociationQuery> queryCaptor = ArgumentCaptor.forClass(ProjectQgateAssociationQuery.class);
+    verify(projectFinder).find(queryCaptor.capture());
+    ProjectQgateAssociationQuery query = queryCaptor.getValue();
+    assertThat(query.membership()).isEqualTo(ProjectQgateAssociationQuery.ANY);
+  }
+
+  @Test
+  public void search_nominal() throws Exception {
+    long gateId = 12345L;
+    Association assoc = mock(Association.class);
+    when(assoc.hasMoreResults()).thenReturn(true);
+    List<ProjectQgateAssociation> projects = ImmutableList.of(
+      new ProjectQgateAssociation().setId(24L).setName("Project Two").setMember(true)
+      );
+    when(assoc.projects()).thenReturn(projects);
+    when(projectFinder.find(any(ProjectQgateAssociationQuery.class))).thenReturn(assoc);
+
+    tester.newGetRequest("api/qualitygates", "search")
+      .setParam("gateId", Long.toString(gateId))
+      .execute()
+      .assertJson("{\"more\":true,\"results\":["
+        + "{\"id\":24,\"name\":\"Project Two\",\"selected\":true}"
+        + "]}");
+    ArgumentCaptor<ProjectQgateAssociationQuery> queryCaptor = ArgumentCaptor.forClass(ProjectQgateAssociationQuery.class);
+    verify(projectFinder).find(queryCaptor.capture());
+    ProjectQgateAssociationQuery query = queryCaptor.getValue();
+    assertThat(query.membership()).isEqualTo(ProjectQgateAssociationQuery.IN);
+  }
+
+  @Test
+  public void select_nominal() throws Exception {
+    long gateId = 42L;
+    long projectId = 666L;
+    tester.newPostRequest("api/qualitygates", "select")
+      .setParam("gateId", Long.toString(gateId))
+      .setParam("projectId", Long.toString(projectId))
+      .execute()
+      .assertNoContent();
+    verify(qGates).associateProject(gateId, projectId);
+  }
+
+  @Test
+  public void deselect_nominal() throws Exception {
+    long gateId = 42L;
+    long projectId = 666L;
+    tester.newPostRequest("api/qualitygates", "deselect")
+      .setParam("gateId", Long.toString(gateId))
+      .setParam("projectId", Long.toString(projectId))
+      .execute()
+      .assertNoContent();
+    verify(qGates).dissociateProject(gateId, projectId);
+  }
+}