Details:
- Probe key |
- Maximum value |
- Status |
+ Value |
+ Weight |
Message |
-
-
|
- |
+
+ |
+ |
-
-
- |
-
-
-
- Not executed.
- This probes requires
-
-
- ,
-
- to be successful to be executed.
-
+
|
@@ -93,30 +74,28 @@ Details:
Probes results
-
+
ID |
Status |
Message |
- Description |
-
-
|
+
+
|
-
-
+
+
|
|
- |
-
+
No probe were executed on the plugin yet.
diff --git a/war/src/main/resources/templates/scores/listing.html b/war/src/main/resources/templates/scores/listing.html
index 312f4b803..935e26e42 100644
--- a/war/src/main/resources/templates/scores/listing.html
+++ b/war/src/main/resources/templates/scores/listing.html
@@ -13,18 +13,19 @@ Scores
Key |
Weight |
- Probe(s) used |
+ What is validated |
Description |
|
- |
+ |
-
+
|
|
diff --git a/war/src/test/java/io/jenkins/pluginhealth/scoring/http/ScoreAPITest.java b/war/src/test/java/io/jenkins/pluginhealth/scoring/http/ScoreAPITest.java
index d3c985745..e180b4b52 100644
--- a/war/src/test/java/io/jenkins/pluginhealth/scoring/http/ScoreAPITest.java
+++ b/war/src/test/java/io/jenkins/pluginhealth/scoring/http/ScoreAPITest.java
@@ -31,17 +31,16 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.time.ZonedDateTime;
+import java.util.List;
import java.util.Map;
-import java.util.Optional;
+import java.util.Set;
import io.jenkins.pluginhealth.scoring.config.SecurityConfiguration;
import io.jenkins.pluginhealth.scoring.model.Plugin;
-import io.jenkins.pluginhealth.scoring.model.ProbeResult;
import io.jenkins.pluginhealth.scoring.model.Score;
import io.jenkins.pluginhealth.scoring.model.ScoreResult;
-import io.jenkins.pluginhealth.scoring.scores.Scoring;
+import io.jenkins.pluginhealth.scoring.model.ScoringComponentResult;
import io.jenkins.pluginhealth.scoring.service.ScoreService;
-import io.jenkins.pluginhealth.scoring.service.ScoringService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
@@ -57,67 +56,41 @@
import org.springframework.test.web.servlet.MockMvc;
@ExtendWith({ SpringExtension.class, MockitoExtension.class })
-@ImportAutoConfiguration({ProjectInfoAutoConfiguration.class, SecurityConfiguration.class})
+@ImportAutoConfiguration({ ProjectInfoAutoConfiguration.class, SecurityConfiguration.class })
@WebMvcTest(
controllers = ScoreAPI.class
)
class ScoreAPITest {
@MockBean private ScoreService scoreService;
- @MockBean private ScoringService scoringService;
@Autowired private MockMvc mockMvc;
@Autowired ObjectMapper mapper;
@Test
void shouldBeAbleToProvideScoresSummary() throws Exception {
- final String probe1Key = "probe-1",
- probe2Key = "probe-2",
- probe3Key = "probe-3",
- scoring1Key = "scoring-1",
- scoring2Key = "scoring-2";
-
- final Plugin plugin1 = mock(Plugin.class);
- when(plugin1.getDetails()).thenReturn(Map.of(
- probe1Key, ProbeResult.success(probe1Key, "")
- ));
-
- final Plugin plugin2 = mock(Plugin.class);
- when(plugin2.getDetails()).thenReturn(Map.of(
- probe1Key, ProbeResult.success(probe1Key, ""),
- probe2Key, ProbeResult.failure(probe2Key, ""),
- probe3Key, ProbeResult.failure(probe3Key, "")
+ final Plugin p1 = mock(Plugin.class);
+ final Plugin p2 = mock(Plugin.class);
+
+ final Score scoreP1 = new Score(p1, ZonedDateTime.now());
+ scoreP1.addDetail(new ScoreResult("scoring-1", 100, 1, Set.of(
+ new ScoringComponentResult(100, 1, List.of("There is no active security advisory for the plugin."))
+ )));
+
+ final Score scoreP2 = new Score(p2, ZonedDateTime.now());
+ scoreP2.addDetail(new ScoreResult("scoring-1", 100, 1, Set.of(
+ new ScoringComponentResult(100, 1, List.of("There is no active security advisory for the plugin."))
+ )));
+ scoreP2.addDetail(new ScoreResult("scoring-2", 50, 1, Set.of(
+ new ScoringComponentResult(0, 1, List.of("There is no Jenkinsfile detected on the plugin repository.")),
+ new ScoringComponentResult(100, .5f, List.of("The plugin documentation was migrated to its repository.")),
+ new ScoringComponentResult(100, .5f, List.of("The plugin is using dependabot.", "0 open pull requests from dependency update tool."))
+ )));
+
+ when(scoreService.getLatestScoresSummaryMap()).thenReturn(Map.of(
+ "plugin-1", scoreP1,
+ "plugin-2", scoreP2
));
-
- final Scoring scoring1 = mock(Scoring.class);
- when(scoring1.getScoreComponents()).thenReturn(Map.of(
- probe1Key, 1f
- ));
- when(scoringService.get(scoring1Key)).thenReturn(Optional.of(scoring1));
-
- final Scoring scoring2 = mock(Scoring.class);
- when(scoring2.getScoreComponents()).thenReturn(Map.of(
- probe2Key, 1f,
- probe3Key, 1f
- ));
- when(scoringService.get(scoring2Key)).thenReturn(Optional.of(scoring2));
-
- final ScoreResult p1sr1 = new ScoreResult(scoring1Key, 1, 1);
- final ScoreResult p2sr1 = new ScoreResult(scoring1Key, 1, 1);
- final ScoreResult p2sr2 = new ScoreResult(scoring2Key, 0, 1);
-
- final Score score1 = new Score(plugin1, ZonedDateTime.now());
- score1.addDetail(p1sr1);
- final Score score2 = new Score(plugin2, ZonedDateTime.now());
- score2.addDetail(p2sr1);
- score2.addDetail(p2sr2);
-
- final Map summary = Map.of(
- "plugin-1", score1,
- "plugin-2", score2
- );
- when(scoreService.getLatestScoresSummaryMap()).thenReturn(summary);
-
when(scoreService.getScoresStatistics()).thenReturn(new ScoreService.ScoreStatistics(
- 50, 0, 100, 100, 100, 100
+ 87.5, 50, 100, 100, 100, 100
));
mockMvc.perform(get("/api/scores"))
@@ -131,38 +104,54 @@ void shouldBeAbleToProvideScoresSummary() throws Exception {
'value': 100,
'details': {
'scoring-1': {
- 'value': 1,
+ 'value': 100,
'weight': 1,
- 'components': {
- 'probe-1': { 'value': 1, 'max': 1 }
- }
+ 'components': [{
+ 'value': 100,
+ 'weight': 1,
+ 'reasons': ['There is no active security advisory for the plugin.']
+ }]
}
}
},
'plugin-2': {
- 'value': 50,
+ 'value': 75,
'details': {
'scoring-1': {
- 'value': 1,
+ 'value': 100,
'weight': 1,
- 'components': {
- 'probe-1': { 'value': 1, 'max': 1 }
- }
+ 'components': [{
+ 'value': 100,
+ 'weight': 1,
+ 'reasons': ['There is no active security advisory for the plugin.']
+ }]
},
'scoring-2': {
- 'value': 0,
+ 'value': 50,
'weight': 1,
- 'components': {
- 'probe-2': { 'value': 0, 'max': 1 },
- 'probe-3': { 'value': 0, 'max': 1 }
- }
+ 'components': [{
+ 'value': 0,
+ 'weight': 1,
+ 'reasons': ['There is no Jenkinsfile detected on the plugin repository.']
+ }, {
+ 'value': 100,
+ 'weight': .5,
+ 'reasons': ['The plugin documentation was migrated to its repository.']
+ }, {
+ 'value': 100,
+ 'weight': .5,
+ 'reasons': [
+ 'The plugin is using dependabot.',
+ '0 open pull requests from dependency update tool.'
+ ]
+ }]
}
}
}
},
'statistics': {
- 'average': 50,
- 'minimum': 0,
+ 'average': 87.5,
+ 'minimum': 50,
'maximum': 100,
'firstQuartile': 100,
'median': 100,
diff --git a/war/src/test/java/io/jenkins/pluginhealth/scoring/http/ScoreControllerTest.java b/war/src/test/java/io/jenkins/pluginhealth/scoring/http/ScoreControllerTest.java
index 13e39f047..67cb3f92d 100644
--- a/war/src/test/java/io/jenkins/pluginhealth/scoring/http/ScoreControllerTest.java
+++ b/war/src/test/java/io/jenkins/pluginhealth/scoring/http/ScoreControllerTest.java
@@ -34,6 +34,7 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import java.time.ZonedDateTime;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -43,7 +44,8 @@
import io.jenkins.pluginhealth.scoring.model.ProbeResult;
import io.jenkins.pluginhealth.scoring.model.Score;
import io.jenkins.pluginhealth.scoring.model.ScoreResult;
-import io.jenkins.pluginhealth.scoring.service.ProbeService;
+import io.jenkins.pluginhealth.scoring.scores.Scoring;
+import io.jenkins.pluginhealth.scoring.scores.ScoringComponent;
import io.jenkins.pluginhealth.scoring.service.ScoreService;
import io.jenkins.pluginhealth.scoring.service.ScoringService;
@@ -65,13 +67,37 @@
controllers = ScoreController.class
)
class ScoreControllerTest {
- @MockBean private ProbeService probeService;
@MockBean private ScoreService scoreService;
@MockBean private ScoringService scoringService;
@Autowired private MockMvc mockMvc;
@Test
void shouldDisplayListOfScoring() throws Exception {
+ when(scoringService.getScoringList())
+ .thenReturn(List.of(
+ new Scoring() {
+ @Override
+ public String key() {
+ return "foo";
+ }
+
+ @Override
+ public float weight() {
+ return 1;
+ }
+
+ @Override
+ public String description() {
+ return "description";
+ }
+
+ @Override
+ public List getComponents() {
+ return List.of();
+ }
+ }
+ ));
+
mockMvc.perform(get("/scores"))
.andExpect(status().isOk())
.andExpect(view().name("scores/listing"))
@@ -88,7 +114,7 @@ void shouldDisplayScoreForSpecificPlugin() throws Exception {
final Plugin plugin = mock(Plugin.class);
when(plugin.getName()).thenReturn(pluginName);
when(plugin.getDetails()).thenReturn(Map.of(
- probeKey, ProbeResult.success(probeKey, "message")
+ probeKey, ProbeResult.success(probeKey, "message", 1)
));
when(plugin.getScm()).thenReturn("this-is-the-url-of-the-plugin-location");
when(plugin.getReleaseTimestamp()).thenReturn(ZonedDateTime.now().minusHours(1));
@@ -98,7 +124,7 @@ void shouldDisplayScoreForSpecificPlugin() throws Exception {
when(score.getPlugin()).thenReturn(plugin);
when(score.getValue()).thenReturn(42L);
when(score.getDetails()).thenReturn(Set.of(
- new ScoreResult(scoreKey, .42f, 1f)
+ new ScoreResult(scoreKey, 42, 1f, Set.of())
));
when(scoreService.latestScoreFor(pluginName)).thenReturn(Optional.of(score));
@@ -107,7 +133,7 @@ void shouldDisplayScoreForSpecificPlugin() throws Exception {
.andExpect(status().isOk())
.andExpect(view().name("scores/details"))
.andExpect(model().attribute("module", "scores"))
- .andExpect(model().attributeExists("score", "scores", "probes"))
+ .andExpect(model().attributeExists("score"))
/*.andExpect(model().attribute(
"score",
allOf(
diff --git a/war/src/test/java/io/jenkins/pluginhealth/scoring/probes/ProbeEngineTest.java b/war/src/test/java/io/jenkins/pluginhealth/scoring/probes/ProbeEngineTest.java
index 6e06c2091..bcd636842 100644
--- a/war/src/test/java/io/jenkins/pluginhealth/scoring/probes/ProbeEngineTest.java
+++ b/war/src/test/java/io/jenkins/pluginhealth/scoring/probes/ProbeEngineTest.java
@@ -26,7 +26,6 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -36,6 +35,7 @@
import static org.mockito.Mockito.when;
import java.io.IOException;
+import java.nio.file.Files;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;
@@ -44,7 +44,6 @@
import io.jenkins.pluginhealth.scoring.model.Plugin;
import io.jenkins.pluginhealth.scoring.model.ProbeResult;
-import io.jenkins.pluginhealth.scoring.model.ResultStatus;
import io.jenkins.pluginhealth.scoring.model.updatecenter.UpdateCenter;
import io.jenkins.pluginhealth.scoring.service.PluginDocumentationService;
import io.jenkins.pluginhealth.scoring.service.PluginService;
@@ -81,13 +80,13 @@ void shouldBeAbleToRunSimpleProbe() throws IOException {
final Probe probe = spy(Probe.class);
final ProbeContext ctx = mock(ProbeContext.class);
- final ProbeResult expectedResult = ProbeResult.success("foo", "bar");
-
- when(plugin.getName()).thenReturn("foo");
+ final ProbeResult expectedResult = ProbeResult.success("foo", "bar", 1);
+ when(plugin.getDetails()).thenReturn(Map.of());
+ when(probe.key()).thenReturn("probe");
when(probe.doApply(plugin, ctx)).thenReturn(expectedResult);
- when(probeService.getProbeContext(anyString(), any(UpdateCenter.class))).thenReturn(ctx);
+ when(probeService.getProbeContext(any(Plugin.class), any(UpdateCenter.class))).thenReturn(ctx);
when(probeService.getProbes()).thenReturn(List.of(probe));
when(pluginService.streamAll()).thenReturn(Stream.of(plugin));
@@ -108,12 +107,13 @@ void shouldNotApplyProbeWithReleaseRequirementOnPluginWithNoNewReleaseWithPastRe
when(plugin.getName()).thenReturn("foo");
when(plugin.getReleaseTimestamp()).thenReturn(ZonedDateTime.now().minusDays(1));
- when(plugin.getDetails()).thenReturn(Map.of(probeKey, ProbeResult.success(probeKey, "This is good")));
+ when(plugin.getDetails()).thenReturn(Map.of(probeKey, ProbeResult.success(probeKey, "This is good", 1)));
when(probe.requiresRelease()).thenReturn(true);
when(probe.key()).thenReturn(probeKey);
+ when(probe.getVersion()).thenReturn(1L);
- when(probeService.getProbeContext(anyString(), any(UpdateCenter.class))).thenReturn(ctx);
+ when(probeService.getProbeContext(any(Plugin.class), any(UpdateCenter.class))).thenReturn(ctx);
when(probeService.getProbes()).thenReturn(List.of(probe));
when(pluginService.streamAll()).thenReturn(Stream.of(plugin));
@@ -131,15 +131,16 @@ void shouldNotApplyProbeRelatedToCodeWithNoNewCode() throws IOException {
final ProbeContext ctx = mock(ProbeContext.class);
when(plugin.getDetails()).thenReturn(Map.of(
- "probe", new ProbeResult("probe", "message", ResultStatus.SUCCESS, ZonedDateTime.now().minusDays(1))
+ "probe", new ProbeResult("probe", "message", ProbeResult.Status.SUCCESS, ZonedDateTime.now().minusDays(1), 1)
));
when(plugin.getName()).thenReturn("foo");
+ when(probe.getVersion()).thenReturn(1L);
when(probe.key()).thenReturn("probe");
when(probe.requiresRelease()).thenReturn(false);
when(probe.isSourceCodeRelated()).thenReturn(true);
- when(probeService.getProbeContext(anyString(), any(UpdateCenter.class))).thenReturn(ctx);
+ when(probeService.getProbeContext(any(Plugin.class), any(UpdateCenter.class))).thenReturn(ctx);
when(probeService.getProbes()).thenReturn(List.of(probe));
when(pluginService.streamAll()).thenReturn(Stream.of(plugin));
@@ -154,20 +155,23 @@ void shouldApplyProbeRelatedToCodeWithNewCommit() throws IOException {
final Plugin plugin = mock(Plugin.class);
final Probe probe = spy(Probe.class);
final ProbeContext ctx = mock(ProbeContext.class);
- final ProbeResult result = new ProbeResult("probe", "message", ResultStatus.SUCCESS);
+ final String probeKey = "probe";
+
+ final ProbeResult result = new ProbeResult(probeKey, "message", ProbeResult.Status.SUCCESS, 1);
when(plugin.getDetails()).thenReturn(Map.of(
- "probe", new ProbeResult("probe", "message", ResultStatus.SUCCESS, ZonedDateTime.now().minusDays(1))
+ probeKey, new ProbeResult(probeKey, "message", ProbeResult.Status.SUCCESS, ZonedDateTime.now().minusDays(1), 1)
));
- when(plugin.getName()).thenReturn("foo");
+ when(probe.getVersion()).thenReturn(1L);
+ when(ctx.getScmRepository()).thenReturn(Optional.of(Files.createTempDirectory("ProbeEngineTest-shouldApplyProbeRelatedToCodeWithNewCommit")));
when(ctx.getLastCommitDate()).thenReturn(Optional.of(ZonedDateTime.now()));
- when(probe.key()).thenReturn("probe");
+ when(probe.key()).thenReturn(probeKey);
when(probe.isSourceCodeRelated()).thenReturn(true);
when(probe.doApply(plugin, ctx)).thenReturn(result);
- when(probeService.getProbeContext(anyString(), any(UpdateCenter.class))).thenReturn(ctx);
+ when(probeService.getProbeContext(any(Plugin.class), any(UpdateCenter.class))).thenReturn(ctx);
when(probeService.getProbes()).thenReturn(List.of(probe));
when(pluginService.streamAll()).thenReturn(Stream.of(plugin));
@@ -185,15 +189,15 @@ void shouldApplyProbeWithReleaseRequirementOnPluginWithNewReleaseAndPastResult()
final Probe probe = spy(Probe.class);
final ProbeContext ctx = mock(ProbeContext.class);
- when(plugin.getName()).thenReturn("foo");
when(plugin.getReleaseTimestamp()).thenReturn(ZonedDateTime.now());
- when(plugin.getDetails()).thenReturn(Map.of(probeKey, new ProbeResult(probeKey, "this is ok", ResultStatus.SUCCESS, ZonedDateTime.now().minusDays(1))));
+ when(plugin.getDetails()).thenReturn(Map.of(probeKey, new ProbeResult(probeKey, "this is ok", ProbeResult.Status.SUCCESS, ZonedDateTime.now().minusDays(1), 1)));
+ when(probe.getVersion()).thenReturn(1L);
when(probe.key()).thenReturn(probeKey);
when(probe.requiresRelease()).thenReturn(true);
- when(probe.doApply(plugin, ctx)).thenReturn(ProbeResult.success(probeKey, "This is also ok"));
+ when(probe.doApply(plugin, ctx)).thenReturn(ProbeResult.success(probeKey, "This is also ok", 1));
- when(probeService.getProbeContext(anyString(), any(UpdateCenter.class))).thenReturn(ctx);
+ when(probeService.getProbeContext(any(Plugin.class), any(UpdateCenter.class))).thenReturn(ctx);
when(probeService.getProbes()).thenReturn(List.of(probe));
when(pluginService.streamAll()).thenReturn(Stream.of(plugin));
@@ -211,17 +215,17 @@ void shouldApplyProbeWithNoReleaseRequirementOnPluginWithPastResult() throws IOE
final Probe probe = spy(Probe.class);
final ProbeContext ctx = mock(ProbeContext.class);
- when(plugin.getName()).thenReturn("foo");
when(plugin.getDetails()).thenReturn(Map.of(
probeKey,
- new ProbeResult(probeKey, "this is ok", ResultStatus.SUCCESS, ZonedDateTime.now().minusDays(1))
+ new ProbeResult(probeKey, "this is ok", ProbeResult.Status.SUCCESS, ZonedDateTime.now().minusDays(1), 1)
));
+ when(probe.getVersion()).thenReturn(1L);
when(probe.requiresRelease()).thenReturn(false);
- when(probe.doApply(plugin, ctx)).thenReturn(ProbeResult.success(probeKey, "This is also ok"));
+ when(probe.doApply(plugin, ctx)).thenReturn(ProbeResult.success(probeKey, "This is also ok", 1));
when(probe.key()).thenReturn(probeKey);
- when(probeService.getProbeContext(anyString(), any(UpdateCenter.class))).thenReturn(ctx);
+ when(probeService.getProbeContext(any(Plugin.class), any(UpdateCenter.class))).thenReturn(ctx);
when(probeService.getProbes()).thenReturn(List.of(probe));
when(pluginService.streamAll()).thenReturn(Stream.of(plugin));
@@ -233,23 +237,21 @@ void shouldApplyProbeWithNoReleaseRequirementOnPluginWithPastResult() throws IOE
}
@Test
- void shouldNotSaveErrors() throws IOException {
+ void shouldSaveEvenErrors() throws IOException {
final Plugin plugin = mock(Plugin.class);
final Probe probe = spy(Probe.class);
final ProbeContext ctx = mock(ProbeContext.class);
- when(plugin.getName()).thenReturn("foo");
-
- when(probe.doApply(plugin, ctx)).thenReturn(ProbeResult.error("foo", "bar"));
+ when(probe.doApply(plugin, ctx)).thenReturn(ProbeResult.error("foo", "bar", 1));
- when(probeService.getProbeContext(anyString(), any(UpdateCenter.class))).thenReturn(ctx);
+ when(probeService.getProbeContext(any(Plugin.class), any(UpdateCenter.class))).thenReturn(ctx);
when(probeService.getProbes()).thenReturn(List.of(probe));
when(pluginService.streamAll()).thenReturn(Stream.of(plugin));
final ProbeEngine probeEngine = new ProbeEngine(probeService, pluginService, updateCenterService, gitHub, pluginDocumentationService);
probeEngine.run();
- verify(plugin, never()).addDetails(any(ProbeResult.class));
+ verify(plugin).addDetails(any(ProbeResult.class));
}
@Test
@@ -261,8 +263,8 @@ void shouldBeAbleToGetPreviousContextResultInExecution() throws IOException {
@Override
protected ProbeResult doApply(Plugin plugin, ProbeContext ctx) {
return plugin.getDetails().get("foo") != null ?
- ProbeResult.success(key(), "This is also ok") :
- ProbeResult.error(key(), "This cannot be validated");
+ ProbeResult.success(key(), "This is also ok", this.getVersion()) :
+ ProbeResult.error(key(), "This cannot be validated", this.getVersion());
}
@Override
@@ -274,14 +276,17 @@ public String key() {
public String getDescription() {
return "description";
}
- };
- when(plugin.getName()).thenReturn("foo");
+ @Override
+ public long getVersion() {
+ return 1;
+ }
+ };
when(probeOne.key()).thenReturn("foo");
- when(probeOne.doApply(plugin, ctx)).thenReturn(ProbeResult.success("foo", "This is ok"));
+ when(probeOne.doApply(plugin, ctx)).thenReturn(ProbeResult.success("foo", "This is ok", 1));
- when(probeService.getProbeContext(anyString(), any(UpdateCenter.class))).thenReturn(ctx);
+ when(probeService.getProbeContext(any(Plugin.class), any(UpdateCenter.class))).thenReturn(ctx);
when(probeService.getProbes()).thenReturn(List.of(probeOne, probeTwo));
when(pluginService.streamAll()).thenReturn(Stream.of(plugin));
@@ -291,4 +296,57 @@ public String getDescription() {
verify(plugin, times(2)).addDetails(any(ProbeResult.class));
assertThat(plugin.getDetails().keySet()).containsExactlyInAnyOrder("foo", "bar");
}
+
+ @Test
+ void shouldForceProbeExecutionWhenNewVersionOfTheProbe() throws IOException {
+ final String probeKey = "foo";
+ final long version = 1L;
+ final ProbeResult newProbeResult = new ProbeResult(
+ probeKey, "this is a message", ProbeResult.Status.SUCCESS, version + 1
+ );
+
+ final Plugin plugin = mock(Plugin.class);
+ final Probe probe = spy(new Probe() {
+ @Override
+ protected ProbeResult doApply(Plugin plugin, ProbeContext context) {
+ return newProbeResult;
+ }
+
+ @Override
+ public String key() {
+ return probeKey;
+ }
+
+ @Override
+ public String getDescription() {
+ return "";
+ }
+
+ @Override
+ public long getVersion() {
+ return version + 1;
+ }
+
+ @Override
+ protected boolean isSourceCodeRelated() {
+ return true;
+ }
+ });
+ final ProbeContext ctx = mock(ProbeContext.class);
+
+ final ProbeResult previousResult = new ProbeResult(probeKey, "this is a message", ProbeResult.Status.SUCCESS, version);
+ when(plugin.getDetails()).thenReturn(Map.of(
+ probeKey, previousResult
+ ));
+
+ when(probeService.getProbeContext(any(Plugin.class), any(UpdateCenter.class))).thenReturn(ctx);
+ when(probeService.getProbes()).thenReturn(List.of(probe));
+ when(pluginService.streamAll()).thenReturn(Stream.of(plugin));
+
+ final ProbeEngine probeEngine = new ProbeEngine(probeService, pluginService, updateCenterService, gitHub, pluginDocumentationService);
+ probeEngine.run();
+
+ verify(probe).doApply(plugin, ctx);
+ verify(plugin).addDetails(newProbeResult);
+ }
}
diff --git a/war/src/test/java/io/jenkins/pluginhealth/scoring/scores/ScoringEngineTest.java b/war/src/test/java/io/jenkins/pluginhealth/scoring/scores/ScoringEngineTest.java
index eed8a2e42..1073e6483 100644
--- a/war/src/test/java/io/jenkins/pluginhealth/scoring/scores/ScoringEngineTest.java
+++ b/war/src/test/java/io/jenkins/pluginhealth/scoring/scores/ScoringEngineTest.java
@@ -37,11 +37,11 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.Set;
import java.util.stream.Stream;
import io.jenkins.pluginhealth.scoring.model.Plugin;
import io.jenkins.pluginhealth.scoring.model.ProbeResult;
-import io.jenkins.pluginhealth.scoring.model.ResultStatus;
import io.jenkins.pluginhealth.scoring.model.Score;
import io.jenkins.pluginhealth.scoring.model.ScoreResult;
import io.jenkins.pluginhealth.scoring.service.PluginService;
@@ -68,8 +68,8 @@ void shouldBeAbleToScoreOnePlugin() {
final Scoring scoringB = mock(Scoring.class);
when(plugin.getName()).thenReturn("foo-bar");
- when(scoringA.apply(plugin)).thenReturn(new ScoreResult("scoring-a", 1, .5f));
- when(scoringB.apply(plugin)).thenReturn(new ScoreResult("scoring-b", 0, 1));
+ when(scoringA.apply(plugin)).thenReturn(new ScoreResult("scoring-a", 100, .5f, Set.of()));
+ when(scoringB.apply(plugin)).thenReturn(new ScoreResult("scoring-b", 0, 1, Set.of()));
when(scoringService.getScoringList()).thenReturn(List.of(scoringA, scoringB));
when(scoreService.save(any(Score.class))).then(AdditionalAnswers.returnsFirstArg());
@@ -80,6 +80,7 @@ void shouldBeAbleToScoreOnePlugin() {
verify(scoringA).apply(plugin);
verify(scoringB).apply(plugin);
+ assertThat(score).isNotNull();
assertThat(score.getPlugin()).isEqualTo(plugin);
assertThat(score.getDetails()).hasSize(2);
assertThat(score.getValue()).isEqualTo(33);
@@ -98,8 +99,8 @@ void shouldBeAbleToScoreMultiplePlugins() {
when(pluginB.getName()).thenReturn("plugin-b");
when(pluginC.getName()).thenReturn("plugin-c");
- when(scoringA.apply(any(Plugin.class))).thenReturn(new ScoreResult("scoring-a", 1, 0.5f));
- when(scoringB.apply(any(Plugin.class))).thenReturn(new ScoreResult("scoring-b", .75f, .75f));
+ when(scoringA.apply(any(Plugin.class))).thenReturn(new ScoreResult("scoring-a", 100, 0.5f, Set.of()));
+ when(scoringB.apply(any(Plugin.class))).thenReturn(new ScoreResult("scoring-b", 75, .75f, Set.of()));
when(scoringService.getScoringList()).thenReturn(List.of(scoringA, scoringB));
when(pluginService.streamAll()).thenReturn(Stream.of(pluginA, pluginB, pluginC));
@@ -128,7 +129,7 @@ void shouldOnlyScorePluginsWithNewerResultThanLatestScore() {
final String pluginName = "plugin-a";
when(pluginA.getName()).thenReturn(pluginName);
when(pluginA.getDetails()).thenReturn(Map.of(
- "foo-bar", new ProbeResult("foo-bar", "", ResultStatus.FAILURE, ZonedDateTime.now().minusMinutes(15))
+ "foo-bar", new ProbeResult("foo-bar", "", ProbeResult.Status.SUCCESS, ZonedDateTime.now().minusMinutes(15), 1)
));
final Scoring scoringA = mock(Scoring.class);
|