From df4ae5e2bd6a144ad36e4b028a8b7f71ab188d3a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Lievremont Date: Tue, 18 Mar 2014 13:40:20 +0100 Subject: SONAR-5091 Force selection of period for new_* metrics, show delta in period label --- ..._quality_gate_detail_condition_template.hbs.erb | 8 ++-- .../quality-gate-detail-condition-view.coffee | 3 +- .../views/quality-gate-detail-condition-view.js | 44 +++++++++++++--------- 3 files changed, 33 insertions(+), 22 deletions(-) (limited to 'sonar-server') diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_condition_template.hbs.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_condition_template.hbs.erb index 6023e5b4357..95ace5887a9 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_condition_template.hbs.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_condition_template.hbs.erb @@ -5,11 +5,13 @@ {{#if canEdit}} {{else}} - {{periodText}} + {{#if periodText}}Δ {{periodText}} + {{else}}{{t 'value'}} + {{/if}} {{/if}} diff --git a/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-condition-view.coffee b/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-condition-view.coffee index da1b8d46f04..26f23dbc32e 100644 --- a/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-condition-view.coffee +++ b/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-condition-view.coffee @@ -42,6 +42,7 @@ define [ metricKey = @model.get('metric') metric = _.findWhere @options.app.metrics, key: metricKey @model.set { metric: metric }, { silent: true } + @model.set { isDiffMetric: metric.key.indexOf('new_') == 0 }, { silent: true } onRender: -> @@ -105,7 +106,7 @@ define [ serializeData: -> - period = _.findWhere(@options.app.periods, key: '' + this.model.get('period')) + period = _.findWhere(@options.app.periods, key: this.model.get('period')) _.extend super, canEdit: @options.app.canEdit periods: @options.app.periods diff --git a/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-condition-view.js b/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-condition-view.js index 0abc1b0532b..d18fa24aff0 100644 --- a/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-condition-view.js +++ b/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-condition-view.js @@ -1,16 +1,15 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; define(['backbone.marionette', 'handlebars'], function(Marionette, Handlebars) { - var QualityGateDetailConditionView, _ref; + var QualityGateDetailConditionView; return QualityGateDetailConditionView = (function(_super) { __extends(QualityGateDetailConditionView, _super); function QualityGateDetailConditionView() { - _ref = QualityGateDetailConditionView.__super__.constructor.apply(this, arguments); - return _ref; + return QualityGateDetailConditionView.__super__.constructor.apply(this, arguments); } QualityGateDetailConditionView.prototype.tagName = 'tr'; @@ -51,11 +50,16 @@ metric = _.findWhere(this.options.app.metrics, { key: metricKey }); - return this.model.set({ + this.model.set({ metric: metric }, { silent: true }); + return this.model.set({ + isDiffMetric: metric.key.indexOf('new_') === 0 + }, { + silent: true + }); }; QualityGateDetailConditionView.prototype.onRender = function() { @@ -89,7 +93,6 @@ }; QualityGateDetailConditionView.prototype.saveCondition = function() { - var _this = this; this.showSpinner(); this.model.set({ period: this.ui.periodSelect.val(), @@ -97,22 +100,27 @@ warning: this.ui.warningInput.val(), error: this.ui.errorInput.val() }); - return this.model.save().always(function() { - _this.ui.updateButton.prop('disabled', true); - return _this.hideSpinner(); - }).done(function() { - return _this.options.collectionView.updateConditions(); - }); + return this.model.save().always((function(_this) { + return function() { + _this.ui.updateButton.prop('disabled', true); + return _this.hideSpinner(); + }; + })(this)).done((function(_this) { + return function() { + return _this.options.collectionView.updateConditions(); + }; + })(this)); }; QualityGateDetailConditionView.prototype.deleteCondition = function() { - var _this = this; if (confirm(t('are_you_sure'))) { this.showSpinner(); - return this.model["delete"]().done(function() { - _this.options.collectionView.updateConditions(); - return _this.close(); - }); + return this.model["delete"]().done((function(_this) { + return function() { + _this.options.collectionView.updateConditions(); + return _this.close(); + }; + })(this)); } }; @@ -127,7 +135,7 @@ QualityGateDetailConditionView.prototype.serializeData = function() { var period; period = _.findWhere(this.options.app.periods, { - key: '' + this.model.get('period') + key: this.model.get('period') }); return _.extend(QualityGateDetailConditionView.__super__.serializeData.apply(this, arguments), { canEdit: this.options.app.canEdit, -- cgit v1.2.3 From 24151eab4a10a3fc4d283e0efdc87dd5f56261b4 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Lievremont Date: Tue, 18 Mar 2014 13:50:15 +0100 Subject: SONAR-5091 Allow deletion of default quality gate --- .../main/java/org/sonar/server/qualitygate/QualityGates.java | 6 +++--- .../java/org/sonar/server/qualitygate/QualityGatesTest.java | 12 +++++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'sonar-server') diff --git a/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java b/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java index 10ab51f61a5..5f51aa76eb8 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java +++ b/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java @@ -139,11 +139,11 @@ public class QualityGates { public void delete(long idToDelete) { checkPermission(UserSession.get()); QualityGateDto qGate = getNonNullQgate(idToDelete); - if (isDefault(qGate)) { - throw new BadRequestException("Impossible to delete default quality gate."); - } SqlSession session = myBatis.openSession(); try { + if (isDefault(qGate)) { + propertiesDao.deleteGlobalProperty(SONAR_QUALITYGATE_PROPERTY, session); + } propertiesDao.deleteProjectProperties(SONAR_QUALITYGATE_PROPERTY, Long.toString(idToDelete), session); dao.delete(qGate, session); session.commit(); diff --git a/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java b/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java index 55ef7f025a5..31fb5d55716 100644 --- a/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java +++ b/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java @@ -257,14 +257,20 @@ public class QualityGatesTest { verify(dao).delete(toDelete, session); } - @Test(expected = BadRequestException.class) - public void should_not_delete_qgate_if_default() throws Exception { + @Test + public void should_delete_qgate_even_if_default() throws Exception { long idToDelete = 42L; String name = "To Delete"; QualityGateDto toDelete = new QualityGateDto().setId(idToDelete).setName(name); when(dao.selectById(idToDelete)).thenReturn(toDelete); - when(propertiesDao.selectGlobalProperty("sonar.qualitygate")).thenReturn(new PropertyDto().setValue(Long.toString(idToDelete))); + when(propertiesDao.selectGlobalProperty("sonar.qualitygate")).thenReturn(new PropertyDto().setValue("42")); + SqlSession session = mock(SqlSession.class); + when(myBatis.openSession()).thenReturn(session); qGates.delete(idToDelete); + verify(dao).selectById(idToDelete); + verify(propertiesDao).deleteGlobalProperty("sonar.qualitygate", session); + verify(propertiesDao).deleteProjectProperties("sonar.qualitygate", "42", session); + verify(dao).delete(toDelete, session); } @Test -- cgit v1.2.3 From b447bcd53e30432c43b9808d10e576cc95764182 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Lievremont Date: Tue, 18 Mar 2014 13:55:37 +0100 Subject: SONAR-5091 Fix icon wrapping under input field --- .../templates/_quality_gate_detail_condition_template.hbs.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sonar-server') diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_condition_template.hbs.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_condition_template.hbs.erb index 95ace5887a9..7ca50016040 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_condition_template.hbs.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_condition_template.hbs.erb @@ -25,7 +25,7 @@ {{t 'quality_gates.operator' op}} {{/if}} - + {{#if canEdit}} @@ -33,7 +33,7 @@ {{warning}} {{/if}} - + {{#if canEdit}} -- cgit v1.2.3 From d8615a4edd4f958109de1b8dcd3caebb8958a55e Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 18 Mar 2014 14:58:27 +0100 Subject: SONAR-5056 Add create profile --- .../core/technicaldebt/db/CharacteristicDao.java | 41 ++++++- .../technicaldebt/db/CharacteristicMapper.java | 4 + .../core/technicaldebt/db/CharacteristicMapper.xml | 18 +++ .../technicaldebt/db/CharacteristicDaoTest.java | 23 ++++ ...order_when_characteristics_are_all_disabled.xml | 13 +++ .../db/CharacteristicDaoTest/shared.xml | 4 +- .../org/sonar/server/debt/DebtModelService.java | 54 ++++++++- .../webapp/WEB-INF/app/models/characteristic.rb | 11 +- .../sonar/server/debt/DebtModelServiceTest.java | 130 +++++++++++++++++---- 9 files changed, 263 insertions(+), 35 deletions(-) create mode 100644 sonar-core/src/test/resources/org/sonar/core/technicaldebt/db/CharacteristicDaoTest/select_max_characteristic_order_when_characteristics_are_all_disabled.xml (limited to 'sonar-server') diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDao.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDao.java index 42ef216b738..0699b48354c 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDao.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDao.java @@ -39,7 +39,6 @@ public class CharacteristicDao implements BatchComponent, ServerComponent { /** * @return enabled root characteristics and characteristics - * */ public List selectEnabledCharacteristics() { SqlSession session = mybatis.openSession(); @@ -56,7 +55,6 @@ public class CharacteristicDao implements BatchComponent, ServerComponent { /** * @return all characteristics - * */ public List selectCharacteristics() { SqlSession session = mybatis.openSession(); @@ -76,14 +74,20 @@ public class CharacteristicDao implements BatchComponent, ServerComponent { */ public List selectEnabledRootCharacteristics() { SqlSession session = mybatis.openSession(); - CharacteristicMapper mapper = session.getMapper(CharacteristicMapper.class); try { - return mapper.selectEnabledRootCharacteristics(); + return selectEnabledRootCharacteristics(session); } finally { MyBatis.closeQuietly(session); } } + /** + * @return only enabled root characteristics, order by order + */ + public List selectEnabledRootCharacteristics(SqlSession session) { + return session.getMapper(CharacteristicMapper.class).selectEnabledRootCharacteristics(); + } + @CheckForNull public CharacteristicDto selectByKey(String key) { SqlSession session = mybatis.openSession(); @@ -106,6 +110,35 @@ public class CharacteristicDao implements BatchComponent, ServerComponent { } } + @CheckForNull + public CharacteristicDto selectByName(String name) { + SqlSession session = mybatis.openSession(); + try { + return selectByName(name, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public CharacteristicDto selectByName(String name, SqlSession session) { + return session.getMapper(CharacteristicMapper.class).selectByName(name); + } + + public int selectMaxCharacteristicOrder() { + SqlSession session = mybatis.openSession(); + try { + return selectMaxCharacteristicOrder(session); + } finally { + MyBatis.closeQuietly(session); + } + } + + public int selectMaxCharacteristicOrder(SqlSession session) { + Integer result = session.getMapper(CharacteristicMapper.class).selectMaxCharacteristicOrder(); + return result != null ? result : 0; + } + public void insert(CharacteristicDto dto, SqlSession session) { session.getMapper(CharacteristicMapper.class).insert(dto); } diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicMapper.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicMapper.java index 8557c307c3e..b63e89ad456 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicMapper.java @@ -34,6 +34,10 @@ public interface CharacteristicMapper { CharacteristicDto selectById(int id); + CharacteristicDto selectByName(String name); + + Integer selectMaxCharacteristicOrder(); + void insert(CharacteristicDto characteristic); int update(CharacteristicDto characteristic); diff --git a/sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml b/sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml index 4cf3ea98e7f..d598985763c 100644 --- a/sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml @@ -56,6 +56,24 @@ + + + + INSERT INTO characteristics (kee, name, parent_id, characteristic_order, enabled, created_at, updated_at) VALUES (#{kee}, #{name}, #{parentId}, #{characteristicOrder}, #{enabled}, current_timestamp, current_timestamp) diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/db/CharacteristicDaoTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/db/CharacteristicDaoTest.java index 1a3fa00574a..82f6dba1d01 100644 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/db/CharacteristicDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/db/CharacteristicDaoTest.java @@ -119,6 +119,15 @@ public class CharacteristicDaoTest extends AbstractDaoTestCase { assertThat(dao.selectByKey("UNKNOWN")).isNull(); } + @Test + public void select_characteristic_by_name() { + setupData("shared"); + + assertThat(dao.selectByName("Portability")).isNotNull(); + assertThat(dao.selectByName("Compiler related portability")).isNotNull(); + assertThat(dao.selectByName("Unknown")).isNull(); + } + @Test public void select_characteristic_by_id() { setupData("shared"); @@ -129,6 +138,20 @@ public class CharacteristicDaoTest extends AbstractDaoTestCase { assertThat(dao.selectById(10)).isNull(); } + @Test + public void select_max_characteristic_order() { + setupData("shared"); + + assertThat(dao.selectMaxCharacteristicOrder()).isEqualTo(1); + } + + @Test + public void select_max_characteristic_order_when_characteristics_are_all_disabled() { + setupData("select_max_characteristic_order_when_characteristics_are_all_disabled"); + + assertThat(dao.selectMaxCharacteristicOrder()).isEqualTo(0); + } + @Test public void insert_characteristic() throws Exception { CharacteristicDto dto = new CharacteristicDto() diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/db/CharacteristicDaoTest/select_max_characteristic_order_when_characteristics_are_all_disabled.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/db/CharacteristicDaoTest/select_max_characteristic_order_when_characteristics_are_all_disabled.xml new file mode 100644 index 00000000000..78e951519bd --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/db/CharacteristicDaoTest/select_max_characteristic_order_when_characteristics_are_all_disabled.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/db/CharacteristicDaoTest/shared.xml b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/db/CharacteristicDaoTest/shared.xml index e8c52c0a142..499959e3c3a 100644 --- a/sonar-core/src/test/resources/org/sonar/core/technicaldebt/db/CharacteristicDaoTest/shared.xml +++ b/sonar-core/src/test/resources/org/sonar/core/technicaldebt/db/CharacteristicDaoTest/shared.xml @@ -6,7 +6,7 @@ created_at="2013-11-20" updated_at="2013-11-22"/> - @@ -16,7 +16,7 @@ created_at="2013-11-20" updated_at="2013-11-22"/> - diff --git a/sonar-server/src/main/java/org/sonar/server/debt/DebtModelService.java b/sonar-server/src/main/java/org/sonar/server/debt/DebtModelService.java index a5a32807add..4d314d96d5a 100644 --- a/sonar-server/src/main/java/org/sonar/server/debt/DebtModelService.java +++ b/sonar-server/src/main/java/org/sonar/server/debt/DebtModelService.java @@ -22,13 +22,19 @@ package org.sonar.server.debt; import com.google.common.base.Function; import com.google.common.collect.Iterables; +import org.apache.ibatis.session.SqlSession; import org.sonar.api.server.debt.DebtCharacteristic; import org.sonar.api.server.debt.DebtModel; import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic; +import org.sonar.core.persistence.MyBatis; import org.sonar.core.technicaldebt.db.CharacteristicDao; import org.sonar.core.technicaldebt.db.CharacteristicDto; +import org.sonar.server.exceptions.BadRequestException; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.util.Validation; import javax.annotation.CheckForNull; +import javax.annotation.Nullable; import java.util.Collection; import java.util.List; @@ -37,12 +43,15 @@ import static com.google.common.collect.Lists.newArrayList; /** * Used through ruby code
Internal.debt
+ * Also used by SQALE plugin. */ public class DebtModelService implements DebtModel { + private final MyBatis mybatis; private final CharacteristicDao dao; - public DebtModelService(CharacteristicDao dao) { + public DebtModelService(MyBatis mybatis, CharacteristicDao dao) { + this.mybatis = mybatis; this.dao = dao; } @@ -60,6 +69,49 @@ public class DebtModelService implements DebtModel { return dto != null ? toCharacteristic(dto) : null; } + public DebtCharacteristic createCharacteristic(String name, @Nullable Integer parentId) { + SqlSession session = mybatis.openSession(); + try { + checkNotAlreadyExists(name, session); + + CharacteristicDto newCharacteristic = new CharacteristicDto() + .setKey(name.toUpperCase().replace(" ", "_")) + .setName(name) + .setEnabled(true); + + // New sub characteristic + if (parentId != null) { + CharacteristicDto parent = findCharacteristic(parentId); + if (parent.getParentId() != null) { + throw new BadRequestException("A sub characteristic can not have a sub characteristic as parent."); + } + newCharacteristic.setParentId(parent.getId()); + } else { + // New root characteristic + newCharacteristic.setOrder(dao.selectMaxCharacteristicOrder(session)+1); + } + dao.insert(newCharacteristic, session); + session.commit(); + return toCharacteristic(newCharacteristic); + } finally { + MyBatis.closeQuietly(session); + } + } + + private CharacteristicDto findCharacteristic(Integer id){ + CharacteristicDto dto = dao.selectById(id); + if (dto == null) { + throw new NotFoundException(String.format("Characteristic with id %s does not exists.", id)); + } + return dto; + } + + private void checkNotAlreadyExists(String name, SqlSession session) { + if (dao.selectByName(name, session) != null) { + throw BadRequestException.ofL10n(Validation.IS_ALREADY_USED_MESSAGE, name); + } + } + private static List toCharacteristics(Collection dtos) { return newArrayList(Iterables.transform(dtos, new Function() { @Override diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/characteristic.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/characteristic.rb index e04b5154720..42708225ed8 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/characteristic.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/characteristic.rb @@ -30,10 +30,9 @@ class Characteristic < ActiveRecord::Base MINUTE = "mn" belongs_to :parent, :class_name => 'Characteristic', :foreign_key => 'parent_id' - belongs_to :rule - validates_uniqueness_of :name, :scope => [:enabled], :case_sensitive => false, :if => Proc.new { |c| c.rule_id.nil? && c.enabled } - validates_length_of :name, :in => 1..NAME_MAX_SIZE, :allow_blank => false, :if => Proc.new { |c| c.rule_id.nil? } + validates_uniqueness_of :name, :scope => [:enabled], :case_sensitive => false, :if => Proc.new { |c| c.enabled } + validates_length_of :name, :in => 1..NAME_MAX_SIZE, :allow_blank => false def root? parent_id.nil? @@ -48,11 +47,7 @@ class Characteristic < ActiveRecord::Base end def name(rule_name_if_empty=false) - result=read_attribute(:name) - if (result.nil? && rule_name_if_empty && rule_id) - result=rule.name - end - result + read_attribute(:name) end end diff --git a/sonar-server/src/test/java/org/sonar/server/debt/DebtModelServiceTest.java b/sonar-server/src/test/java/org/sonar/server/debt/DebtModelServiceTest.java index 8a59e05b387..3277e46cf90 100644 --- a/sonar-server/src/test/java/org/sonar/server/debt/DebtModelServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/debt/DebtModelServiceTest.java @@ -19,17 +19,26 @@ */ package org.sonar.server.debt; +import org.apache.ibatis.session.SqlSession; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; import org.sonar.api.server.debt.DebtCharacteristic; +import org.sonar.core.persistence.MyBatis; import org.sonar.core.technicaldebt.db.CharacteristicDao; import org.sonar.core.technicaldebt.db.CharacteristicDto; +import org.sonar.server.exceptions.BadRequestException; +import org.sonar.server.exceptions.NotFoundException; import static com.google.common.collect.Lists.newArrayList; import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) @@ -38,51 +47,132 @@ public class DebtModelServiceTest { @Mock CharacteristicDao dao; + @Mock + MyBatis mybatis; + + @Mock + SqlSession session; + DebtModelService service; + CharacteristicDto rootCharacteristicDto = new CharacteristicDto() + .setId(1) + .setKey("MEMORY_EFFICIENCY") + .setName("Memory use") + .setOrder(1); + + CharacteristicDto characteristicDto = new CharacteristicDto() + .setId(2) + .setKey("EFFICIENCY") + .setName("Efficiency") + .setParentId(1); + + int currentId; + @Before public void setUp() throws Exception { - service = new DebtModelService(dao); + currentId = 10; + + // Associate an id when inserting an object to simulate the db id generator + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) { + Object[] args = invocation.getArguments(); + CharacteristicDto dto = (CharacteristicDto) args[0]; + dto.setId(++currentId); + return null; + } + }).when(dao).insert(any(CharacteristicDto.class), any(SqlSession.class)); + + when(mybatis.openSession()).thenReturn(session); + service = new DebtModelService(mybatis, dao); } @Test public void find_root_characteristics() { - CharacteristicDto dto = new CharacteristicDto() - .setId(1) - .setKey("MEMORY_EFFICIENCY") - .setName("Memory use"); - when(dao.selectEnabledRootCharacteristics()).thenReturn(newArrayList(dto)); + when(dao.selectEnabledRootCharacteristics()).thenReturn(newArrayList(rootCharacteristicDto)); assertThat(service.rootCharacteristics()).hasSize(1); } @Test public void find_characteristics() { - CharacteristicDto dto = new CharacteristicDto() - .setId(1) - .setKey("MEMORY_EFFICIENCY") - .setName("Memory use"); - when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(dto)); + when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(rootCharacteristicDto)); assertThat(service.characteristics()).hasSize(1); } @Test public void find_characteristic_by_id() { - CharacteristicDto dto = new CharacteristicDto() - .setId(1) - .setKey("MEMORY_EFFICIENCY") - .setName("Memory use") - .setParentId(2) - .setOrder(1); - when(dao.selectById(1)).thenReturn(dto); + when(dao.selectById(1)).thenReturn(rootCharacteristicDto); DebtCharacteristic characteristic = service.characteristicById(1); assertThat(characteristic.id()).isEqualTo(1); assertThat(characteristic.key()).isEqualTo("MEMORY_EFFICIENCY"); assertThat(characteristic.name()).isEqualTo("Memory use"); - assertThat(characteristic.parentId()).isEqualTo(2); assertThat(characteristic.order()).isEqualTo(1); + assertThat(characteristic.parentId()).isNull(); + + assertThat(service.characteristicById(111)).isNull(); + } + + @Test + public void create_sub_characteristic() { + when(dao.selectById(1)).thenReturn(rootCharacteristicDto); + + DebtCharacteristic result = service.createCharacteristic("Compilation name", 1); + + assertThat(result.id()).isEqualTo(currentId); + assertThat(result.key()).isEqualTo("COMPILATION_NAME"); + assertThat(result.name()).isEqualTo("Compilation name"); + assertThat(result.parentId()).isEqualTo(1); + } + + @Test + public void fail_to_create_sub_characteristic_when_parent_id_is_not_a_root_characteristic() { + when(dao.selectById(1)).thenReturn(characteristicDto); + + try { + service.createCharacteristic("Compilation", 1); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("A sub characteristic can not have a sub characteristic as parent."); + } + } + + @Test + public void fail_to_create_sub_characteristic_when_parent_does_not_exists() { + when(dao.selectById(1)).thenReturn(null); + + try { + service.createCharacteristic("Compilation", 1); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("Characteristic with id 1 does not exists."); + } + } + + @Test + public void fail_to_create_sub_characteristic_when_name_already_used() { + when(dao.selectByName("Compilation", session)).thenReturn(new CharacteristicDto()); + when(dao.selectById(1)).thenReturn(rootCharacteristicDto); + + try { + service.createCharacteristic("Compilation", 1); + fail(); + } catch (BadRequestException e) { + assertThat(e.l10nKey()).isEqualTo("errors.is_already_used"); + assertThat(e.l10nParams().iterator().next()).isEqualTo("Compilation"); + } + } + + @Test + public void create_characteristic() { + when(dao.selectMaxCharacteristicOrder(session)).thenReturn(1); + + DebtCharacteristic result = service.createCharacteristic("Portability", null); - assertThat(service.characteristicById(10)).isNull(); + assertThat(result.id()).isEqualTo(currentId); + assertThat(result.key()).isEqualTo("PORTABILITY"); + assertThat(result.name()).isEqualTo("Portability"); + assertThat(result.order()).isEqualTo(2); } } -- cgit v1.2.3 From 152cf9835b1cfd4a817b83ec48e2b1f474e8490f Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Tue, 18 Mar 2014 15:22:28 +0100 Subject: SONAR-5143 revert. Inclusions are coming back to UI ! Conflicts: sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql sonar-server/src/main/webapp/WEB-INF/db/migrate/499_delete_inclusions_properties.rb --- .../sonar/plugins/core/ExclusionProperties.java | 10 +++---- .../org/sonar/core/persistence/rows-h2.sql | 1 - .../db/migrate/499_delete_inclusions_properties.rb | 35 ---------------------- 3 files changed, 4 insertions(+), 42 deletions(-) delete mode 100644 sonar-server/src/main/webapp/WEB-INF/db/migrate/499_delete_inclusions_properties.rb (limited to 'sonar-server') diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/ExclusionProperties.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/ExclusionProperties.java index 00d7e7c0611..b169a572965 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/ExclusionProperties.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/ExclusionProperties.java @@ -34,24 +34,22 @@ class ExclusionProperties { static List definitions() { return ImmutableList.of( - - // Do not display inclusions in UI - // https://jira.codehaus.org/browse/SONAR-5143 PropertyDefinition.builder(CoreProperties.PROJECT_INCLUSIONS_PROPERTY) .name("Source File Inclusions") .multiValues(true) .category(CoreProperties.CATEGORY_EXCLUSIONS) .subCategory(CoreProperties.SUBCATEGORY_FILES_EXCLUSIONS) - .hidden() + .onQualifiers(Qualifiers.PROJECT) + .index(3) .build(), PropertyDefinition.builder(CoreProperties.PROJECT_TEST_INCLUSIONS_PROPERTY) .name("Test File Inclusions") .multiValues(true) .category(CoreProperties.CATEGORY_EXCLUSIONS) .subCategory(CoreProperties.SUBCATEGORY_FILES_EXCLUSIONS) - .hidden() + .onQualifiers(Qualifiers.PROJECT) + .index(5) .build(), - PropertyDefinition.builder(CoreProperties.GLOBAL_EXCLUSIONS_PROPERTY) .name("Global Source File Exclusions") .multiValues(true) diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql index d01a3101ee4..b924803a886 100644 --- a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql +++ b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql @@ -208,7 +208,6 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('495'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('496'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('497'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('498'); -INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('499'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('510'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('511'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('512'); diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/499_delete_inclusions_properties.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/499_delete_inclusions_properties.rb deleted file mode 100644 index 84a8bfb9899..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/db/migrate/499_delete_inclusions_properties.rb +++ /dev/null @@ -1,35 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2013 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -# -# SonarQube 4.2 -# SONAR-5143 -# -class DeleteInclusionsProperties < ActiveRecord::Migration - - class Property < ActiveRecord::Base - end - - def self.up - Property.delete_all("prop_key = 'sonar.inclusions'") - Property.delete_all("prop_key = 'sonar.test.inclusions'") - end - -end -- cgit v1.2.3 From d79c15d37b89d887c349e5066bf01e62659c2596 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 18 Mar 2014 17:24:30 +0100 Subject: SONAR-5056 Create rename, move up and move down actions --- .../core/technicaldebt/db/CharacteristicDao.java | 48 ++++++- .../technicaldebt/db/CharacteristicMapper.java | 4 + .../core/technicaldebt/db/CharacteristicMapper.xml | 22 +++ .../technicaldebt/db/CharacteristicDaoTest.java | 11 ++ .../select_next_and_previous.xml | 13 ++ .../org/sonar/server/debt/DebtModelService.java | 72 +++++++++- .../sonar/server/debt/DebtModelServiceTest.java | 147 ++++++++++++++++++--- 7 files changed, 290 insertions(+), 27 deletions(-) create mode 100644 sonar-core/src/test/resources/org/sonar/core/technicaldebt/db/CharacteristicDaoTest/select_next_and_previous.xml (limited to 'sonar-server') diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDao.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDao.java index 0699b48354c..05555a28486 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDao.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicDao.java @@ -91,25 +91,33 @@ public class CharacteristicDao implements BatchComponent, ServerComponent { @CheckForNull public CharacteristicDto selectByKey(String key) { SqlSession session = mybatis.openSession(); - CharacteristicMapper mapper = session.getMapper(CharacteristicMapper.class); try { - return mapper.selectByKey(key); + return selectByKey(key, session); } finally { MyBatis.closeQuietly(session); } } + @CheckForNull + public CharacteristicDto selectByKey(String key, SqlSession session) { + return session.getMapper(CharacteristicMapper.class).selectByKey(key); + } + @CheckForNull public CharacteristicDto selectById(int id) { SqlSession session = mybatis.openSession(); - CharacteristicMapper mapper = session.getMapper(CharacteristicMapper.class); try { - return mapper.selectById(id); + return selectById(id, session); } finally { MyBatis.closeQuietly(session); } } + @CheckForNull + public CharacteristicDto selectById(int id, SqlSession session) { + return session.getMapper(CharacteristicMapper.class).selectById(id); + } + @CheckForNull public CharacteristicDto selectByName(String name) { SqlSession session = mybatis.openSession(); @@ -125,6 +133,38 @@ public class CharacteristicDao implements BatchComponent, ServerComponent { return session.getMapper(CharacteristicMapper.class).selectByName(name); } + @CheckForNull + public CharacteristicDto selectNext(int order, SqlSession session) { + List dtos = session.getMapper(CharacteristicMapper.class).selectNext(order); + return dtos.isEmpty() ? null : dtos.get(0); + } + + @CheckForNull + public CharacteristicDto selectNext(int order) { + SqlSession session = mybatis.openSession(); + try { + return selectNext(order, session); + } finally { + MyBatis.closeQuietly(session); + } + } + + @CheckForNull + public CharacteristicDto selectPrevious(int order, SqlSession session) { + List dtos = session.getMapper(CharacteristicMapper.class).selectPrevious(order); + return dtos.isEmpty() ? null : dtos.get(0); + } + + @CheckForNull + public CharacteristicDto selectPrevious(int order) { + SqlSession session = mybatis.openSession(); + try { + return selectPrevious(order, session); + } finally { + MyBatis.closeQuietly(session); + } + } + public int selectMaxCharacteristicOrder() { SqlSession session = mybatis.openSession(); try { diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicMapper.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicMapper.java index b63e89ad456..fe995a8c078 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/db/CharacteristicMapper.java @@ -36,6 +36,10 @@ public interface CharacteristicMapper { CharacteristicDto selectByName(String name); + List selectNext(int order); + + List selectPrevious(int order); + Integer selectMaxCharacteristicOrder(); void insert(CharacteristicDto characteristic); diff --git a/sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml b/sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml index d598985763c..e4cde1a0ac8 100644 --- a/sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml @@ -65,6 +65,28 @@ + + + +