From 7e354d6ec2afc5e34df9c8f56fad4167cde8a3b5 Mon Sep 17 00:00:00 2001 From: Markus Heberling Date: Mon, 13 Jan 2020 10:59:00 +0100 Subject: [PATCH 1/2] Fix test on non-us systems --- .../sonarqube/plugin/ce/pullrequest/AnalysisDetails.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/AnalysisDetails.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/AnalysisDetails.java index 134f993ed..c712fcb44 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/AnalysisDetails.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/AnalysisDetails.java @@ -48,10 +48,12 @@ import java.math.BigDecimal; import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.util.Arrays; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; @@ -124,7 +126,7 @@ public String createAnalysisSummary(FormatterFactory formatterFactory) { double duplications = findMeasure(CoreMetrics.DUPLICATED_LINES_DENSITY_KEY).map(MeasureWrapper::getDoubleValue).orElse(0D); - NumberFormat decimalFormat = new DecimalFormat("#0.00"); + NumberFormat decimalFormat = new DecimalFormat("#0.00", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); Map issueCounts = countRuleByType(); long issueTotal = issueCounts.values().stream().mapToLong(l -> l).sum(); @@ -302,7 +304,7 @@ private static String format(QualityGate.Condition condition) { condition.getOperator() == QualityGate.Operator.GREATER_THAN ? "is worse than" : "is better than", Rating.valueOf(Integer.parseInt(condition.getErrorThreshold()))); } else if (metric.getType() == Metric.ValueType.PERCENT) { - NumberFormat numberFormat = new DecimalFormat("#0.00"); + NumberFormat numberFormat = new DecimalFormat("#0.00", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); return String.format("%s%% %s (%s %s%%)", numberFormat.format(new BigDecimal(condition.getValue())), metric.getName(), condition.getOperator() == QualityGate.Operator.GREATER_THAN ? "is greater than" : From 4e37a61c203f80e6aaa2b6ab935de0da3bfc44d6 Mon Sep 17 00:00:00 2001 From: Markus Heberling Date: Mon, 13 Jan 2020 10:01:46 +0100 Subject: [PATCH 2/2] add link to SonarQube fixes a part of #67 --- .../ce/pullrequest/AnalysisDetails.java | 12 +++-- .../PullRequestPostAnalysisTask.java | 8 +++- .../ce/pullrequest/markup/BaseFormatter.java | 2 + .../pullrequest/markup/FormatterFactory.java | 2 + .../plugin/ce/pullrequest/markup/Heading.java | 2 +- .../plugin/ce/pullrequest/markup/Link.java | 38 ++++++++++++++++ .../ce/pullrequest/markup/ListItem.java | 2 +- .../markup/MarkdownFormatterFactory.java | 10 +++++ .../ce/pullrequest/markup/Paragraph.java | 2 +- .../ce/pullrequest/AnalysisDetailsTest.java | 43 +++++++++++------- .../PullRequestPostAnalysisTaskTest.java | 29 +++++++----- .../ce/pullrequest/markup/HeadingTest.java | 5 +++ .../ce/pullrequest/markup/LinkTest.java | 45 +++++++++++++++++++ .../ce/pullrequest/markup/ListItemTest.java | 5 +++ .../markup/MarkdownFormatterFactoryTest.java | 7 +++ .../ce/pullrequest/markup/ParagraphTest.java | 4 ++ 16 files changed, 182 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/Link.java create mode 100644 src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/LinkTest.java diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/AnalysisDetails.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/AnalysisDetails.java index c712fcb44..cdfbfa486 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/AnalysisDetails.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/AnalysisDetails.java @@ -25,6 +25,7 @@ import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.FormatterFactory; import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Heading; import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Image; +import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Link; import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.ListItem; import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Node; import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Paragraph; @@ -47,6 +48,7 @@ import org.sonar.server.measure.Rating; import java.math.BigDecimal; +import java.net.URLEncoder; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; @@ -73,6 +75,7 @@ public class AnalysisDetails { public static final String IMAGE_URL_BASE = "com.github.mc1arke.sonarqube.plugin.branch.image-url-base"; + private final String publicRootURL; private final BranchDetails branchDetails; private final MeasuresHolder measuresHolder; private final PostAnalysisIssueVisitor postAnalysisIssueVisitor; @@ -83,8 +86,9 @@ public class AnalysisDetails { AnalysisDetails(BranchDetails branchDetails, PostAnalysisIssueVisitor postAnalysisIssueVisitor, QualityGate qualityGate, MeasuresHolder measuresHolder, Analysis analysis, Project project, - Configuration configuration) { + Configuration configuration, String publicRootURL) { super(); + this.publicRootURL = publicRootURL; this.branchDetails = branchDetails; this.measuresHolder = measuresHolder; this.postAnalysisIssueVisitor = postAnalysisIssueVisitor; @@ -180,7 +184,8 @@ public String createAnalysisSummary(FormatterFactory formatterFactory) { .map(i -> i + "% Duplicated Code") .orElse("No duplication information") + " (" + decimalFormat.format(duplications) + - "% Estimated after merge)")))); + "% Estimated after merge)"))), + new Link(publicRootURL + "/dashboard?id=" + URLEncoder.encode(project.getKey()) + "&pullRequest=" + branchDetails.getBranchName(), new Text("View in SonarQube"))); return formatterFactory.documentFormatter().format(document, formatterFactory); } @@ -202,7 +207,8 @@ public String createAnalysisIssueSummary(PostAnalysisIssueVisitor.ComponentIssue new Paragraph(new Text(String.format("**Severity:** %s ", issue.severity())), new Image(issue.severity(), String.format("%s/checks/Severity/%s.svg?sanitize=true", baseImageUrl, issue.severity().toLowerCase()))), new Paragraph(new Text(String.format("**Message:** %s", issue.getMessage()))), effortNode, - resolutionNode + resolutionNode, + new Link(publicRootURL + "/project/issues?id=" + URLEncoder.encode(project.getKey()) + "&pullRequest=" + branchDetails.getBranchName() + "&issues=" + issue.key() + "&open=" + issue.key(), new Text("View in SonarQube")) ); return formatterFactory.documentFormatter().format(document, formatterFactory); } diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/PullRequestPostAnalysisTask.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/PullRequestPostAnalysisTask.java index e66bf1d2e..6bd076d18 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/PullRequestPostAnalysisTask.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/PullRequestPostAnalysisTask.java @@ -23,6 +23,7 @@ import org.sonar.api.ce.posttask.PostProjectAnalysisTask; import org.sonar.api.ce.posttask.QualityGate; import org.sonar.api.config.Configuration; +import org.sonar.api.platform.Server; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository; @@ -39,18 +40,21 @@ public class PullRequestPostAnalysisTask implements PostProjectAnalysisTask, private static final Logger LOGGER = Loggers.get(PullRequestPostAnalysisTask.class); private final List pullRequestDecorators; + private final Server server; private final ConfigurationRepository configurationRepository; private final PostAnalysisIssueVisitor postAnalysisIssueVisitor; private final MetricRepository metricRepository; private final MeasureRepository measureRepository; private final TreeRootHolder treeRootHolder; - public PullRequestPostAnalysisTask(ConfigurationRepository configurationRepository, + public PullRequestPostAnalysisTask(Server server, + ConfigurationRepository configurationRepository, List pullRequestDecorators, PostAnalysisIssueVisitor postAnalysisIssueVisitor, MetricRepository metricRepository, MeasureRepository measureRepository, TreeRootHolder treeRootHolder) { super(); + this.server = server; this.configurationRepository = configurationRepository; this.pullRequestDecorators = pullRequestDecorators; this.postAnalysisIssueVisitor = postAnalysisIssueVisitor; @@ -119,7 +123,7 @@ public void finished(PostProjectAnalysisTask.ProjectAnalysis projectAnalysis) { postAnalysisIssueVisitor, qualityGate, new AnalysisDetails.MeasuresHolder(metricRepository, measureRepository, treeRootHolder), analysis, - projectAnalysis.getProject(), configuration); + projectAnalysis.getProject(), configuration, server.getPublicRootUrl()); PullRequestBuildStatusDecorator pullRequestDecorator = optionalPullRequestDecorator.get(); LOGGER.info("using pull request decorator" + pullRequestDecorator.name()); diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/BaseFormatter.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/BaseFormatter.java index 38fd7dc47..23080e41b 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/BaseFormatter.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/BaseFormatter.java @@ -41,6 +41,8 @@ private static Formatter formatterFor(FormatterFactory forma return (Formatter) formatterFactory.paragraphFormatter(); } else if (node instanceof Text) { return (Formatter) formatterFactory.textFormatter(); + } else if (node instanceof Link) { + return (Formatter) formatterFactory.linkFormatter(); } else { throw new IllegalArgumentException("Unknown node type: " + node.getClass().getName()); } diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/FormatterFactory.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/FormatterFactory.java index 08ee1ac97..6267ee61f 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/FormatterFactory.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/FormatterFactory.java @@ -26,6 +26,8 @@ public interface FormatterFactory { Formatter imageFormatter(); + Formatter linkFormatter(); + Formatter listFormatter(); Formatter listItemFormatter(); diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/Heading.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/Heading.java index a9681f000..43052f167 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/Heading.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/Heading.java @@ -33,6 +33,6 @@ int getLevel() { @Override boolean isValidChild(Node child) { - return child instanceof Text || child instanceof Image; + return child instanceof Text || child instanceof Image || child instanceof Link; } } diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/Link.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/Link.java new file mode 100644 index 000000000..dafd10825 --- /dev/null +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/Link.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 Markus Heberling + * + * 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 com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup; + +public final class Link extends Node { + + private final String url; + + public Link(String url, Node... children) { + super(children); + this.url=url; + } + + public String getUrl() { + return url; + } + + @Override + boolean isValidChild(Node child) { + return child instanceof Text; + } +} diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/ListItem.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/ListItem.java index ad7fd269a..dfea862a7 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/ListItem.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/ListItem.java @@ -26,6 +26,6 @@ public ListItem(Node... children) { @Override boolean isValidChild(Node child) { - return child instanceof Text || child instanceof Image; + return child instanceof Text || child instanceof Image|| child instanceof Link; } } diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/MarkdownFormatterFactory.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/MarkdownFormatterFactory.java index fd9cdfb1f..e6f0b7942 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/MarkdownFormatterFactory.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/MarkdownFormatterFactory.java @@ -55,6 +55,16 @@ public String format(Image node, FormatterFactory formatterFactory) { }; } + @Override + public Formatter linkFormatter() { + return new BaseFormatter() { + @Override + public String format(Link node, FormatterFactory formatterFactory) { + return String.format("[%s](%s)", node.getChildren().isEmpty() ? node.getUrl() : childContents(node, formatterFactory), node.getUrl()); + } + }; + } + @Override public Formatter listFormatter() { return new BaseFormatter() { diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/Paragraph.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/Paragraph.java index c0be0b5da..f71a525c6 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/Paragraph.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/Paragraph.java @@ -26,6 +26,6 @@ public Paragraph(Node... children) { @Override boolean isValidChild(Node child) { - return child instanceof Image || child instanceof Text; + return child instanceof Image || child instanceof Text || child instanceof Link; } } diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/AnalysisDetailsTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/AnalysisDetailsTest.java index 395da1690..923f13fdf 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/AnalysisDetailsTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/AnalysisDetailsTest.java @@ -23,10 +23,13 @@ import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.FormatterFactory; import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Heading; import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Image; +import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Link; import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.List; import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.ListItem; import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Paragraph; import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Text; +import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.sonar.api.ce.posttask.Analysis; @@ -80,7 +83,7 @@ public void testGetBranchName() { AnalysisDetails testCase = new AnalysisDetails(branchDetails, postAnalysisIssueVisitor, qualityGate, measuresHolder, analysis, - project, configuration); + project, configuration, null); assertEquals("branchName", testCase.getBranchName()); } @@ -99,7 +102,7 @@ public void testGetCommitSha() { AnalysisDetails testCase = new AnalysisDetails(branchDetails, postAnalysisIssueVisitor, qualityGate, measuresHolder, analysis, - project, configuration); + project, configuration, null); assertEquals("commitId", testCase.getCommitSha()); } @@ -117,7 +120,7 @@ public void testGetQualityGateStatus() { AnalysisDetails testCase = new AnalysisDetails(branchDetails, postAnalysisIssueVisitor, qualityGate, measuresHolder, analysis, - project, configuration); + project, configuration, null); assertEquals(QualityGate.Status.ERROR, testCase.getQualityGateStatus()); } @@ -135,7 +138,7 @@ public void testGetAnalysisDate() { AnalysisDetails testCase = new AnalysisDetails(branchDetails, postAnalysisIssueVisitor, qualityGate, measuresHolder, analysis, - project, configuration); + project, configuration, null); assertEquals(analysis.getDate(), testCase.getAnalysisDate()); } @@ -153,7 +156,7 @@ public void testGetAnalysisId() { AnalysisDetails testCase = new AnalysisDetails(branchDetails, postAnalysisIssueVisitor, qualityGate, measuresHolder, analysis, - project, configuration); + project, configuration, null); assertEquals("Analysis ID", testCase.getAnalysisId()); } @@ -171,7 +174,7 @@ public void testGetAnalysisProjectKey() { AnalysisDetails testCase = new AnalysisDetails(branchDetails, postAnalysisIssueVisitor, qualityGate, measuresHolder, analysis, - project, configuration); + project, configuration, null); assertEquals("Project Key", testCase.getAnalysisProjectKey()); } @@ -179,6 +182,7 @@ public void testGetAnalysisProjectKey() { @Test public void testCreateAnalysisSummary() { AnalysisDetails.BranchDetails branchDetails = mock(AnalysisDetails.BranchDetails.class); + doReturn("5").when(branchDetails).getBranchName(); TreeRootHolder treeRootHolder = mock(TreeRootHolder.class); AnalysisDetails.MeasuresHolder measuresHolder = mock(AnalysisDetails.MeasuresHolder.class); @@ -288,7 +292,7 @@ public void testCreateAnalysisSummary() { AnalysisDetails testCase = new AnalysisDetails(branchDetails, postAnalysisIssueVisitor, qualityGate, measuresHolder, analysis, - project, configuration); + project, configuration, "http://localhost:9000"); Formatter formatter = mock(Formatter.class); doReturn("formatted content").when(formatter).format(any(), any()); @@ -344,7 +348,8 @@ public void testCreateAnalysisSummary() { new ListItem(new Image("No duplication information", "https://raw.githubusercontent.com/mc1arke/sonarqube-community-branch-plugin/master/src/main/resources/pr-decoration-images/checks/Duplications/NoDuplicationInfo.svg?sanitize=true"), new Text(" "), new Text( - "No duplication information (12.30% Estimated after merge)")))); + "No duplication information (12.30% Estimated after merge)"))), + new Link("http://localhost:9000/dashboard?id=Project+Key&pullRequest=5", new Text("View in SonarQube"))); assertThat(documentArgumentCaptor.getValue()).usingRecursiveComparison().isEqualTo(expectedDocument); @@ -354,6 +359,7 @@ public void testCreateAnalysisSummary() { @Test public void testCreateAnalysisSummary2() { AnalysisDetails.BranchDetails branchDetails = mock(AnalysisDetails.BranchDetails.class); + doReturn("5").when(branchDetails).getBranchName(); TreeRootHolder treeRootHolder = mock(TreeRootHolder.class); AnalysisDetails.MeasuresHolder measuresHolder = mock(AnalysisDetails.MeasuresHolder.class); @@ -395,7 +401,7 @@ public void testCreateAnalysisSummary2() { AnalysisDetails testCase = new AnalysisDetails(branchDetails, postAnalysisIssueVisitor, qualityGate, measuresHolder, analysis, - project, configuration); + project, configuration, "http://localhost:9000"); Formatter formatter = mock(Formatter.class); doReturn("formatted content").when(formatter).format(any(), any()); @@ -440,7 +446,8 @@ public void testCreateAnalysisSummary2() { new ListItem(new Image("20 percent duplication", "https://raw.githubusercontent.com/mc1arke/sonarqube-community-branch-plugin/master/src/main/resources/pr-decoration-images/checks/Duplications/20.svg?sanitize=true"), new Text(" "), new Text( - "18.00% Duplicated Code (21.78% Estimated after merge)")))); + "18.00% Duplicated Code (21.78% Estimated after merge)"))), + new Link("http://localhost:9000/dashboard?id=Project+Key&pullRequest=5", new Text("View in SonarQube"))); assertThat(documentArgumentCaptor.getValue()).usingRecursiveComparison().isEqualTo(expectedDocument); @@ -449,6 +456,7 @@ public void testCreateAnalysisSummary2() { @Test public void testCreateAnalysisSummary3() { AnalysisDetails.BranchDetails branchDetails = mock(AnalysisDetails.BranchDetails.class); + doReturn("5").when(branchDetails).getBranchName(); TreeRootHolder treeRootHolder = mock(TreeRootHolder.class); AnalysisDetails.MeasuresHolder measuresHolder = mock(AnalysisDetails.MeasuresHolder.class); @@ -498,7 +506,7 @@ public void testCreateAnalysisSummary3() { AnalysisDetails testCase = new AnalysisDetails(branchDetails, postAnalysisIssueVisitor, qualityGate, measuresHolder, analysis, - project, configuration); + project, configuration, "http://localhost:9000"); Formatter formatter = mock(Formatter.class); doReturn("formatted content").when(formatter).format(any(), any()); @@ -543,7 +551,8 @@ public void testCreateAnalysisSummary3() { new ListItem(new Image("10 percent duplication", "http://host.name/path/checks/Duplications/10.svg?sanitize=true"), new Text(" "), new Text( - "10.00% Duplicated Code (21.78% Estimated after merge)")))); + "10.00% Duplicated Code (21.78% Estimated after merge)"))), + new Link("http://localhost:9000/dashboard?id=Project+Key&pullRequest=5", new Text("View in SonarQube"))); assertThat(documentArgumentCaptor.getValue()).usingRecursiveComparison().isEqualTo(expectedDocument); @@ -552,6 +561,7 @@ public void testCreateAnalysisSummary3() { @Test public void testCreateAnalysisSummary4() { AnalysisDetails.BranchDetails branchDetails = mock(AnalysisDetails.BranchDetails.class); + doReturn("5").when(branchDetails).getBranchName(); TreeRootHolder treeRootHolder = mock(TreeRootHolder.class); AnalysisDetails.MeasuresHolder measuresHolder = mock(AnalysisDetails.MeasuresHolder.class); @@ -593,7 +603,7 @@ public void testCreateAnalysisSummary4() { AnalysisDetails testCase = new AnalysisDetails(branchDetails, postAnalysisIssueVisitor, qualityGate, measuresHolder, analysis, - project, configuration); + project, configuration, "http://localhost:9000"); Formatter formatter = mock(Formatter.class); doReturn("formatted content").when(formatter).format(any(), any()); @@ -638,7 +648,8 @@ public void testCreateAnalysisSummary4() { new ListItem(new Image("20plus percent duplication", "https://raw.githubusercontent.com/mc1arke/sonarqube-community-branch-plugin/master/src/main/resources/pr-decoration-images/checks/Duplications/20plus.svg?sanitize=true"), new Text(" "), new Text( - "30.00% Duplicated Code (21.78% Estimated after merge)")))); + "30.00% Duplicated Code (21.78% Estimated after merge)"))), + new Link("http://localhost:9000/dashboard?id=Project+Key&pullRequest=5", new Text("View in SonarQube"))); assertThat(documentArgumentCaptor.getValue()).usingRecursiveComparison().isEqualTo(expectedDocument); @@ -686,7 +697,7 @@ public void testCorrectPostAnalysisIssueVisitorReturned() { AnalysisDetails analysisDetails = new AnalysisDetails(mock(AnalysisDetails.BranchDetails.class), postAnalysisIssueVisitor, mock(QualityGate.class), mock(AnalysisDetails.MeasuresHolder.class), - mock(Analysis.class), mock(Project.class), mock(Configuration.class)); + mock(Analysis.class), mock(Project.class), mock(Configuration.class), null); assertSame(postAnalysisIssueVisitor, analysisDetails.getPostAnalysisIssueVisitor()); } @@ -713,7 +724,7 @@ public void testReflectiveOperationPropagated() { AnalysisDetails testCase = new AnalysisDetails(mock(AnalysisDetails.BranchDetails.class), mock(PostAnalysisIssueVisitor.class), qualityGate, measuresHolder, mock(Analysis.class), mock(Project.class), - mock(Configuration.class)); + mock(Configuration.class), null); assertThatThrownBy(() -> testCase.createAnalysisSummary(mock(FormatterFactory.class))) .hasMessage("Could not invoke getDoubleValue").isExactlyInstanceOf(IllegalStateException.class) .hasCauseExactlyInstanceOf(InvocationTargetException.class); diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/PullRequestPostAnalysisTaskTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/PullRequestPostAnalysisTaskTest.java index 86e32502e..2ccaa38f1 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/PullRequestPostAnalysisTaskTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/PullRequestPostAnalysisTaskTest.java @@ -26,6 +26,7 @@ import org.sonar.api.ce.posttask.Project; import org.sonar.api.ce.posttask.QualityGate; import org.sonar.api.config.Configuration; +import org.sonar.api.platform.Server; import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository; import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; import org.sonar.ce.task.projectanalysis.measure.MeasureRepository; @@ -53,6 +54,7 @@ public void testFinishedNonPullRequest() { doReturn(Branch.Type.LONG).when(branch).getType(); doReturn(Optional.of(branch)).when(projectAnalysis).getBranch(); + Server server = mock(Server.class); ConfigurationRepository configurationRepository = mock(ConfigurationRepository.class); List pullRequestBuildStatusDecorators = new ArrayList<>(); PostAnalysisIssueVisitor postAnalysisIssueVisitor = mock(PostAnalysisIssueVisitor.class); @@ -61,7 +63,7 @@ public void testFinishedNonPullRequest() { TreeRootHolder treeRootHolder = mock(TreeRootHolder.class); PullRequestPostAnalysisTask testCase = - new PullRequestPostAnalysisTask(configurationRepository, pullRequestBuildStatusDecorators, + new PullRequestPostAnalysisTask(server, configurationRepository, pullRequestBuildStatusDecorators, postAnalysisIssueVisitor, metricRepository, measureRepository, treeRootHolder); testCase.finished(projectAnalysis); @@ -78,6 +80,7 @@ public void testFinishedNoBranchName() { doReturn(Optional.empty()).when(branch).getName(); doReturn(Optional.of(branch)).when(projectAnalysis).getBranch(); + Server server = mock(Server.class); ConfigurationRepository configurationRepository = mock(ConfigurationRepository.class); List pullRequestBuildStatusDecorators = new ArrayList<>(); PostAnalysisIssueVisitor postAnalysisIssueVisitor = mock(PostAnalysisIssueVisitor.class); @@ -86,7 +89,7 @@ public void testFinishedNoBranchName() { TreeRootHolder treeRootHolder = mock(TreeRootHolder.class); PullRequestPostAnalysisTask testCase = - new PullRequestPostAnalysisTask(configurationRepository, pullRequestBuildStatusDecorators, + new PullRequestPostAnalysisTask(server, configurationRepository, pullRequestBuildStatusDecorators, postAnalysisIssueVisitor, metricRepository, measureRepository, treeRootHolder); testCase.finished(projectAnalysis); @@ -103,6 +106,7 @@ public void testFinishedNoProviderSet() { doReturn(Optional.of("branchName")).when(branch).getName(); doReturn(Optional.of(branch)).when(projectAnalysis).getBranch(); + Server server = mock(Server.class); ConfigurationRepository configurationRepository = mock(ConfigurationRepository.class); List pullRequestBuildStatusDecorators = new ArrayList<>(); PostAnalysisIssueVisitor postAnalysisIssueVisitor = mock(PostAnalysisIssueVisitor.class); @@ -115,7 +119,7 @@ public void testFinishedNoProviderSet() { doReturn(configuration).when(configurationRepository).getConfiguration(); PullRequestPostAnalysisTask testCase = - new PullRequestPostAnalysisTask(configurationRepository, pullRequestBuildStatusDecorators, + new PullRequestPostAnalysisTask(server, configurationRepository, pullRequestBuildStatusDecorators, postAnalysisIssueVisitor, metricRepository, measureRepository, treeRootHolder); testCase.finished(projectAnalysis); @@ -133,6 +137,7 @@ public void testFinishedNoProviderMatchingName() { doReturn(Optional.of("branchName")).when(branch).getName(); doReturn(Optional.of(branch)).when(projectAnalysis).getBranch(); + Server server = mock(Server.class); ConfigurationRepository configurationRepository = mock(ConfigurationRepository.class); List pullRequestBuildStatusDecorators = new ArrayList<>(); PostAnalysisIssueVisitor postAnalysisIssueVisitor = mock(PostAnalysisIssueVisitor.class); @@ -153,7 +158,7 @@ public void testFinishedNoProviderMatchingName() { doReturn(configuration).when(configurationRepository).getConfiguration(); PullRequestPostAnalysisTask testCase = - new PullRequestPostAnalysisTask(configurationRepository, pullRequestBuildStatusDecorators, + new PullRequestPostAnalysisTask(server, configurationRepository, pullRequestBuildStatusDecorators, postAnalysisIssueVisitor, metricRepository, measureRepository, treeRootHolder); testCase.finished(projectAnalysis); @@ -173,6 +178,7 @@ public void testFinishedNoAnalysis() { doReturn(Optional.of("pull-request")).when(branch).getName(); doReturn(Optional.of(branch)).when(projectAnalysis).getBranch(); + Server server = mock(Server.class); ConfigurationRepository configurationRepository = mock(ConfigurationRepository.class); List pullRequestBuildStatusDecorators = new ArrayList<>(); PostAnalysisIssueVisitor postAnalysisIssueVisitor = mock(PostAnalysisIssueVisitor.class); @@ -195,7 +201,7 @@ public void testFinishedNoAnalysis() { doReturn(configuration).when(configurationRepository).getConfiguration(); PullRequestPostAnalysisTask testCase = - new PullRequestPostAnalysisTask(configurationRepository, pullRequestBuildStatusDecorators, + new PullRequestPostAnalysisTask(server, configurationRepository, pullRequestBuildStatusDecorators, postAnalysisIssueVisitor, metricRepository, measureRepository, treeRootHolder); testCase.finished(projectAnalysis); @@ -214,6 +220,7 @@ public void testFinishedAnalysisWithNoRevision() { doReturn(Optional.of("pull-request")).when(branch).getName(); doReturn(Optional.of(branch)).when(projectAnalysis).getBranch(); + Server server = mock(Server.class); ConfigurationRepository configurationRepository = mock(ConfigurationRepository.class); List pullRequestBuildStatusDecorators = new ArrayList<>(); PostAnalysisIssueVisitor postAnalysisIssueVisitor = mock(PostAnalysisIssueVisitor.class); @@ -238,7 +245,7 @@ public void testFinishedAnalysisWithNoRevision() { doReturn(configuration).when(configurationRepository).getConfiguration(); PullRequestPostAnalysisTask testCase = - new PullRequestPostAnalysisTask(configurationRepository, pullRequestBuildStatusDecorators, + new PullRequestPostAnalysisTask(server, configurationRepository, pullRequestBuildStatusDecorators, postAnalysisIssueVisitor, metricRepository, measureRepository, treeRootHolder); testCase.finished(projectAnalysis); @@ -257,6 +264,7 @@ public void testFinishedAnalysisWithNoQualityGate() { doReturn(Optional.of("pull-request")).when(branch).getName(); doReturn(Optional.of(branch)).when(projectAnalysis).getBranch(); + Server server = mock(Server.class); ConfigurationRepository configurationRepository = mock(ConfigurationRepository.class); List pullRequestBuildStatusDecorators = new ArrayList<>(); PostAnalysisIssueVisitor postAnalysisIssueVisitor = mock(PostAnalysisIssueVisitor.class); @@ -281,7 +289,7 @@ public void testFinishedAnalysisWithNoQualityGate() { doReturn(configuration).when(configurationRepository).getConfiguration(); PullRequestPostAnalysisTask testCase = - new PullRequestPostAnalysisTask(configurationRepository, pullRequestBuildStatusDecorators, + new PullRequestPostAnalysisTask(server, configurationRepository, pullRequestBuildStatusDecorators, postAnalysisIssueVisitor, metricRepository, measureRepository, treeRootHolder); testCase.finished(projectAnalysis); @@ -303,6 +311,7 @@ public void testFinishedAnalysisDecorationRequest() { Project project = mock(Project.class); doReturn(project).when(projectAnalysis).getProject(); + Server server = mock(Server.class); ConfigurationRepository configurationRepository = mock(ConfigurationRepository.class); List pullRequestBuildStatusDecorators = new ArrayList<>(); PostAnalysisIssueVisitor postAnalysisIssueVisitor = mock(PostAnalysisIssueVisitor.class); @@ -331,7 +340,7 @@ public void testFinishedAnalysisDecorationRequest() { doReturn(configuration).when(configurationRepository).getConfiguration(); PullRequestPostAnalysisTask testCase = - new PullRequestPostAnalysisTask(configurationRepository, pullRequestBuildStatusDecorators, + new PullRequestPostAnalysisTask(server, configurationRepository, pullRequestBuildStatusDecorators, postAnalysisIssueVisitor, metricRepository, measureRepository, treeRootHolder); testCase.finished(projectAnalysis); @@ -348,13 +357,13 @@ public void testFinishedAnalysisDecorationRequest() { postAnalysisIssueVisitor, qualityGate, new AnalysisDetails.MeasuresHolder(metricRepository, measureRepository, treeRootHolder), analysis, project, - configuration); + configuration, null); assertThat(analysisDetailsArgumentCaptor.getValue()).usingRecursiveComparison().isEqualTo(analysisDetails); } @Test public void testCorrectDescriptionReturnedForTask() { - assertThat(new PullRequestPostAnalysisTask(mock(ConfigurationRepository.class), new ArrayList<>(), + assertThat(new PullRequestPostAnalysisTask(mock(Server.class), mock(ConfigurationRepository.class), new ArrayList<>(), mock(PostAnalysisIssueVisitor.class), mock(MetricRepository.class), mock(MeasureRepository.class), mock(TreeRootHolder.class)) .getDescription()).isEqualTo("Pull Request Decoration"); diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/HeadingTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/HeadingTest.java index 0a9b611d0..3295a32ca 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/HeadingTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/HeadingTest.java @@ -47,4 +47,9 @@ public void checkValidAddChildImage() { assertTrue(new Heading(2).isValidChild(new Image("alt", "src"))); } + @Test + public void checkValidAddChildLink() { + assertTrue(new Heading(2).isValidChild(new Link("url"))); + } + } \ No newline at end of file diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/LinkTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/LinkTest.java new file mode 100644 index 000000000..8b5382f43 --- /dev/null +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/LinkTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 Markus Heberling + * + * 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 com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class LinkTest { + + @Test + public void correctParametersReturned() { + Link image = new Link("url", new Text("Text")); + assertThat(image).extracting(Link::getUrl).isEqualTo("url"); + } + + @Test + public void testIsValidChildInvalidChild() { + assertFalse(new Link("url", new Text("Text")).isValidChild(new Paragraph())); + } + + @Test + public void testIsValidChildValidChildText() { + assertTrue(new Link("url", new Text("Text")).isValidChild(new Text(""))); + } + +} \ No newline at end of file diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/ListItemTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/ListItemTest.java index c7b6500ac..5b4b98355 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/ListItemTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/ListItemTest.java @@ -40,4 +40,9 @@ public void testIsValidChildImage() { assertTrue(new ListItem().isValidChild(new Image("", ""))); } + @Test + public void testIsValidChildLink() { + assertTrue(new ListItem().isValidChild(new Link(""))); + } + } \ No newline at end of file diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/MarkdownFormatterFactoryTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/MarkdownFormatterFactoryTest.java index 02a54f543..0d2890b44 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/MarkdownFormatterFactoryTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/MarkdownFormatterFactoryTest.java @@ -44,6 +44,13 @@ public void testImageFormatter() { assertEquals("![alt](source)", testCase.imageFormatter().format(new Image("alt", "source"), testCase)); } + @Test + public void testLinkFormatter() { + MarkdownFormatterFactory testCase = new MarkdownFormatterFactory(); + assertEquals("[Text](http://url)", testCase.linkFormatter().format(new Link("http://url", new Text("Text")), testCase)); + assertEquals("[http://url](http://url)", testCase.linkFormatter().format(new Link("http://url"), testCase)); + } + @Test public void testListFormatter() { MarkdownFormatterFactory testCase = new MarkdownFormatterFactory(); diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/ParagraphTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/ParagraphTest.java index 1b66dd654..bbc9fd2dd 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/ParagraphTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/markup/ParagraphTest.java @@ -40,4 +40,8 @@ public void testIsValidChildValidChildImage() { assertTrue(new Paragraph().isValidChild(new Image("", ""))); } + @Test + public void testIsValidChildValidChildLink() { + assertTrue(new Paragraph().isValidChild(new Link(""))); + } } \ No newline at end of file