Skip to content

Commit fbbe003

Browse files
authored
BITCONDEC-5: Create JUnit tests (#5)
* Mock CommitService and test method getCommitsOfPullRequest() * Mock ApplicationLinkService * Rename ApiLinkService to JiraClient and add test class for JiraClient * Add version to bitbucket dependencies in pom.xml * Test method getDecisionKnowledgeFromJira() * Enable parsing of single project * Test CompletenessMergeCheck * Add test class for KnowledgeRest class * Add model class and interface for pull requests * Add screenshots to README
1 parent 00d9d02 commit fbbe003

29 files changed

+1351
-252
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
44

5-
## 1.1.0 (2019-05-13)
5+
## 0.1.0 (2019-05-13)
66

77

88
### Bug Fixes

README.md

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,11 @@ For example, the developers responsible for implementing a task must have at lea
1717

1818
## Installation
1919

20-
to support the release and commit standards install commitizen:
21-
```
22-
npm install commitizen -g
23-
```
24-
Install all npm modules:
25-
```
26-
npm install
27-
```
28-
29-
## Commits and releases
30-
31-
after staging the files run:
32-
```
33-
git cz
34-
```
35-
36-
37-
to make a standard release:
38-
```
39-
npm run release
40-
```
41-
4220
### Prerequisites
4321

4422
The following prerequisites are necessary to compile the plug-in from source code:
4523

46-
- Java 8 JDK
24+
- Java 11 JDK
4725
- [Atlassian SDK](https://developer.atlassian.com/docs/getting-started/set-up-the-atlassian-plugin-sdk-and-build-a-project)
4826

4927
### Compilation via Terminal
@@ -66,3 +44,43 @@ atlas-run
6644
### Download of Precompiled .jar-File
6745

6846
The precompiled .jar-File for the latest release can be found here: https://github.com/cures-hub/cures-condec-bitbucket/releases/latest
47+
48+
## User Interface
49+
50+
The ConDec Bitbucket plugin integrates in the pull request page.
51+
The branch can only be merged if at least one decision problem and one decision is documented for every associated Jira issue.
52+
53+
![Bitbucket ConDec plug-in](https://github.com/cures-hub/cures-condec-bitbucket/raw/master/doc/merge_check_tooltip.png)
54+
*Pull request view with disabled merge possibility*
55+
56+
![Bitbucket ConDec plug-in](https://github.com/cures-hub/cures-condec-bitbucket/raw/master/doc/merge_check_detail.png)
57+
*Pull request view with detailed documentation hint*
58+
59+
## Contribution
60+
61+
### Commits and Releases
62+
63+
to support the release and commit standards install commitizen:
64+
65+
```
66+
npm install commitizen -g
67+
```
68+
69+
Install all npm modules:
70+
71+
```
72+
npm install
73+
```
74+
75+
after staging the files run:
76+
77+
```
78+
git cz
79+
```
80+
81+
82+
to make a standard release:
83+
84+
```
85+
npm run release
86+
```

doc/merge_check_detail.png

98.9 KB
Loading

doc/merge_check_tooltip.png

82.7 KB
Loading
24.9 KB
Loading

pom.xml

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,20 @@
4242
</dependency>
4343
<dependency>
4444
<groupId>com.atlassian.bitbucket.server</groupId>
45-
<artifactId>bitbucket-api</artifactId>
45+
<artifactId>bitbucket-spi</artifactId>
46+
<version>${bitbucket.version}</version>
4647
<scope>provided</scope>
4748
</dependency>
4849
<dependency>
4950
<groupId>com.atlassian.bitbucket.server</groupId>
50-
<artifactId>bitbucket-spi</artifactId>
51-
<scope>provided</scope>
51+
<artifactId>bitbucket-test-util</artifactId>
52+
<version>${bitbucket.version}</version>
53+
<scope>test</scope>
5254
</dependency>
5355
<dependency>
5456
<groupId>com.atlassian.bitbucket.server</groupId>
5557
<artifactId>bitbucket-page-objects</artifactId>
58+
<version>${bitbucket.version}</version>
5659
<scope>provided</scope>
5760
</dependency>
5861
<dependency>
@@ -190,39 +193,39 @@
190193
</plugin>
191194
</plugins>
192195
</build>
193-
196+
194197
<profiles>
195-
<!-- Creates coverage reports in target/site/jacoco/ -->
196-
<profile>
197-
<id>jacoco</id>
198-
<activation>
199-
<activeByDefault>false</activeByDefault>
200-
</activation>
201-
<build>
202-
<plugins>
203-
<plugin>
204-
<groupId>org.jacoco</groupId>
205-
<artifactId>jacoco-maven-plugin</artifactId>
206-
<version>${jacoco-version}</version>
207-
<executions>
208-
<execution>
209-
<goals>
210-
<goal>prepare-agent</goal>
211-
</goals>
212-
</execution>
213-
<!-- attached to Maven test phase -->
214-
<execution>
215-
<id>report</id>
216-
<phase>test</phase>
217-
<goals>
218-
<goal>report</goal>
219-
</goals>
220-
</execution>
221-
</executions>
222-
</plugin>
223-
</plugins>
224-
</build>
225-
</profile>
198+
<!-- Creates coverage reports in target/site/jacoco/ -->
199+
<profile>
200+
<id>jacoco</id>
201+
<activation>
202+
<activeByDefault>false</activeByDefault>
203+
</activation>
204+
<build>
205+
<plugins>
206+
<plugin>
207+
<groupId>org.jacoco</groupId>
208+
<artifactId>jacoco-maven-plugin</artifactId>
209+
<version>${jacoco-version}</version>
210+
<executions>
211+
<execution>
212+
<goals>
213+
<goal>prepare-agent</goal>
214+
</goals>
215+
</execution>
216+
<!-- attached to Maven test phase -->
217+
<execution>
218+
<id>report</id>
219+
<phase>test</phase>
220+
<goals>
221+
<goal>report</goal>
222+
</goals>
223+
</execution>
224+
</executions>
225+
</plugin>
226+
</plugins>
227+
</build>
228+
</profile>
226229
</profiles>
227230

228231
<properties>
@@ -233,7 +236,7 @@
233236
<jacoco-version>0.8.4</jacoco-version>
234237
<!-- This key is used to keep the consistency between the key in atlassian-plugin.xml and the key to
235238
generate bundle. -->
236-
<atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>
239+
<atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>
237240
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
238241
<maven.compiler.source>11</maven.compiler.source>
239242
<maven.compiler.target>11</maven.compiler.target>
Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package de.uhd.ifi.se.decision.management.bitbucket.merge.checks;
22

3-
import java.util.Locale;
43
import java.util.Set;
54

65
/**
@@ -22,25 +21,4 @@ public interface CompletenessCheckHandler {
2221
* @return set of Jira issue keys.
2322
*/
2423
Set<String> getJiraIssuesWithIncompleteDocumentation();
25-
26-
/**
27-
* Looks for the first Jira issue key (e.g. CONDEC-1) in a String and returns the
28-
* Jira project key (e.g. CONDEC).
29-
*
30-
* @param text
31-
* that might contain a project key, e.g., a commit message, branch
32-
* name oder pull request title.
33-
* @return potential project key in upper case.
34-
*/
35-
static String retrieveProjectKey(String text) {
36-
if (text.indexOf("-") == -1) {
37-
// there is no Jira issue key (e.g. CONDEC-1) in the text
38-
return "";
39-
}
40-
String splitted = text.split("-")[0];
41-
String[] words = splitted.split(" ");
42-
String projectKey = words[words.length - 1];
43-
return projectKey.toUpperCase(Locale.ENGLISH);
44-
}
45-
4624
}

src/main/java/de/uhd/ifi/se/decision/management/bitbucket/merge/checks/CompletenessMergeCheck.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
import com.atlassian.bitbucket.hook.repository.PullRequestMergeHookRequest;
99
import com.atlassian.bitbucket.hook.repository.RepositoryHookResult;
1010
import com.atlassian.bitbucket.hook.repository.RepositoryMergeCheck;
11-
import com.atlassian.bitbucket.pull.PullRequest;
1211

1312
import de.uhd.ifi.se.decision.management.bitbucket.merge.checks.impl.CompletenessCheckHandlerImpl;
13+
import de.uhd.ifi.se.decision.management.bitbucket.model.PullRequest;
14+
import de.uhd.ifi.se.decision.management.bitbucket.model.impl.PullRequestImpl;
1415

1516
/**
1617
* Enforces that pull requests can only be accepted, i.e., the respective branch
@@ -26,7 +27,7 @@ public class CompletenessMergeCheck implements RepositoryMergeCheck {
2627
@Override
2728
public RepositoryHookResult preUpdate(@Nonnull PreRepositoryHookContext context,
2829
@Nonnull PullRequestMergeHookRequest request) {
29-
PullRequest pullRequest = request.getPullRequest();
30+
PullRequest pullRequest = new PullRequestImpl(request);
3031

3132
CompletenessCheckHandler completenessCheckHandler = new CompletenessCheckHandlerImpl(pullRequest);
3233
if (completenessCheckHandler.isDocumentationComplete()) {

src/main/java/de/uhd/ifi/se/decision/management/bitbucket/merge/checks/impl/CompletenessCheckHandlerImpl.java

Lines changed: 4 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,32 @@
11
package de.uhd.ifi.se.decision.management.bitbucket.merge.checks.impl;
22

3-
import java.util.ArrayList;
43
import java.util.HashSet;
54
import java.util.Set;
65

76
import org.json.JSONArray;
87
import org.json.JSONObject;
98

10-
import com.atlassian.bitbucket.commit.Commit;
11-
import com.atlassian.bitbucket.commit.CommitService;
12-
import com.atlassian.bitbucket.commit.CommitsBetweenRequest;
13-
import com.atlassian.bitbucket.pull.PullRequest;
14-
import com.atlassian.bitbucket.pull.PullRequestRef;
15-
import com.atlassian.bitbucket.util.Page;
16-
import com.atlassian.bitbucket.util.PageRequestImpl;
17-
import com.atlassian.sal.api.component.ComponentLocator;
18-
199
import de.uhd.ifi.se.decision.management.bitbucket.merge.checks.CompletenessCheckHandler;
20-
import de.uhd.ifi.se.decision.management.bitbucket.oauth.ApiLinkService;
10+
import de.uhd.ifi.se.decision.management.bitbucket.model.PullRequest;
11+
import de.uhd.ifi.se.decision.management.bitbucket.oauth.JiraClient;
2112

2213
/**
2314
* Class to check the completeness of the documentation of decision knowledge
2415
* related to a pull request.
2516
*/
2617
public class CompletenessCheckHandlerImpl implements CompletenessCheckHandler {
2718

28-
public static String JIRA_QUERY;
29-
public static String PROJECT_KEY;
30-
private PullRequest pullRequest;
19+
public PullRequest pullRequest;
3120
private Set<String> jiraIssuesWithIncompleteDocumentation;
3221

3322
public CompletenessCheckHandlerImpl(PullRequest pullRequest) {
3423
this.pullRequest = pullRequest;
3524
this.jiraIssuesWithIncompleteDocumentation = new HashSet<String>();
3625
}
3726

38-
public Iterable<Commit> getCommitsOfPullRequest() {
39-
try {
40-
CommitService commitService = ComponentLocator.getComponent(CommitService.class);
41-
CommitsBetweenRequest.Builder builder = new CommitsBetweenRequest.Builder(pullRequest);
42-
CommitsBetweenRequest commitsBetweenRequest = builder.build();
43-
Page<Commit> pageWithCommits = commitService.getCommitsBetween(commitsBetweenRequest,
44-
new PageRequestImpl(0, 1048476));
45-
return pageWithCommits.getValues();
46-
} catch (NullPointerException e) {
47-
48-
}
49-
return new ArrayList<Commit>();
50-
}
51-
52-
/**
53-
* @param commits
54-
* @param branchId
55-
* @return String "(TEST-5, TEST-7,etc...)"
56-
*/
57-
public String getJiraCallQuery(Iterable<Commit> commits, String branchId, String branchTitle) {
58-
String query = "(";
59-
ArrayList<String> messageList = new ArrayList<String>();
60-
61-
for (Commit commit : commits) {
62-
String message = commit.getMessage();
63-
messageList.add(message);
64-
}
65-
for (String message : messageList) {
66-
// Split message after first space
67-
if (message.contains(" ")) {
68-
String[] parts = message.split(" ");
69-
query = query + parts[0] + ",";
70-
}
71-
}
72-
73-
// add Branch ID
74-
query += branchId + ",";
75-
// add Branch Title
76-
77-
query += branchTitle;
78-
// add )
79-
query += ")";
80-
return query;
81-
}
82-
8327
@Override
8428
public boolean isDocumentationComplete() {
85-
// find correct query out of projects, commitMessages and BranchId
86-
Iterable<Commit> commits = getCommitsOfPullRequest();
87-
String pullRequestTitle = pullRequest.getTitle();
88-
PullRequestRef pullRequestRef = pullRequest.getFromRef();
89-
String branchName = pullRequestRef.getDisplayId();
90-
String queryWithJiraIssues = "?jql=key in " + getJiraCallQuery(commits, pullRequestTitle, branchName);
91-
92-
JIRA_QUERY = queryWithJiraIssues;
93-
PROJECT_KEY = getProjectKeyFromJiraAndCheckWhichOneCouldBe(commits, branchName, pullRequestTitle);
94-
95-
// get decision knowledge out of Jira
96-
String knowledgeElementsAsJsonString = ApiLinkService.instance.getDecisionKnowledgeFromJira(queryWithJiraIssues,
97-
PROJECT_KEY);
98-
29+
String knowledgeElementsAsJsonString = JiraClient.instance.getDecisionKnowledgeFromJira(pullRequest.getJiraIssueKeys());
9930
return isDocumentationComplete(knowledgeElementsAsJsonString);
10031
}
10132

@@ -137,37 +68,6 @@ public boolean checkIfDecisionsExists(JSONArray decisions) {
13768
return hasIssue && hasDecision;
13869
}
13970

140-
public String getProjectKeyFromJiraAndCheckWhichOneCouldBe(Iterable<Commit> commits, String branchId,
141-
String branchTitle) {
142-
Set<String> projectKeys = ApiLinkService.instance.getCurrentActiveJiraProjects();
143-
144-
// check branch name, e.g. "CONDEC-1.create.a.great.plugin"
145-
String projectKey = CompletenessCheckHandler.retrieveProjectKey(branchId);
146-
if (isProjectKeyExisting(projectKey, projectKeys)) {
147-
return projectKey;
148-
}
149-
150-
// check pull request title, e.g. "ConDec-1: Create a great plugin"
151-
String projectKeyInBranchName = CompletenessCheckHandler.retrieveProjectKey(branchTitle);
152-
if (isProjectKeyExisting(projectKeyInBranchName, projectKeys)) {
153-
return branchTitle;
154-
}
155-
156-
// check commit messages
157-
for (Commit commit : commits) {
158-
String projectKeyInCommitMessage = CompletenessCheckHandler.retrieveProjectKey(commit.getMessage());
159-
if (isProjectKeyExisting(projectKeyInCommitMessage, projectKeys)) {
160-
return projectKeyInCommitMessage;
161-
}
162-
}
163-
164-
return "";
165-
}
166-
167-
private boolean isProjectKeyExisting(String projectKey, Set<String> projectKeys) {
168-
return !projectKey.isEmpty() && projectKeys.contains(projectKey);
169-
}
170-
17171
public Set<String> getJiraIssuesWithIncompleteDocumentation() {
17272
return jiraIssuesWithIncompleteDocumentation;
17373
}

0 commit comments

Comments
 (0)