Skip to content

Commit 778045c

Browse files
authored
Merge pull request #9 from reportportal/EPMRPP-97593-update-dependencies
EPMRPP-97593 update dependencies. add unit test
2 parents 6d1f45e + 3d16856 commit 778045c

File tree

8 files changed

+482
-19
lines changed

8 files changed

+482
-19
lines changed

build.gradle

+14-4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ dependencyManagement {
3838
}
3939
}
4040

41+
ext['junit-jupiter.version'] = "${junitVersion}"
42+
4143
dependencies {
4244
if (releaseMode) {
4345
implementation 'com.epam.reportportal:commons-dao'
@@ -49,12 +51,19 @@ dependencies {
4951
annotationProcessor 'com.github.reportportal:plugin-api:develop-SNAPSHOT'
5052
}
5153

52-
implementation("com.slack.api:slack-api-client:1.27.1") {
53-
exclude group: "org.slf4j"
54-
}
54+
compileOnly "org.projectlombok:lombok:${lombokVersion}"
55+
annotationProcessor "org.projectlombok:lombok:${lombokVersion}"
56+
testCompileOnly "org.projectlombok:lombok:${lombokVersion}"
57+
testAnnotationProcessor "org.projectlombok:lombok:${lombokVersion}"
58+
5559
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2'
56-
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
5760
implementation 'org.hibernate:hibernate-core:5.6.15.Final'
61+
testImplementation 'org.mockito:mockito-core:5.14.2'
62+
testImplementation 'org.mockito:mockito-junit-jupiter:5.14.2'
63+
testImplementation "org.junit.jupiter:junit-jupiter"
64+
testImplementation "org.junit.jupiter:junit-jupiter-api"
65+
testImplementation "org.junit.jupiter:junit-jupiter-engine"
66+
testImplementation 'net.bytebuddy:byte-buddy:1.14.9'
5867
}
5968

6069
test {
@@ -115,6 +124,7 @@ shadowJar {
115124
configurations = [project.configurations.compileClasspath]
116125
zip64 true
117126
dependencies {
127+
include(dependency('commons-io:commons-io:2.15.1'))
118128
}
119129
}
120130

gradle.properties

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
version=1.0.0
22
description=EPAM Report Portal. Slack plugin.
33
pluginId = slack
4+
lombokVersion=1.18.36
5+
junitVersion=5.11.0

src/main/java/com/epam/reportportal/extension/slack/SlackPluginExtension.java

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
* Copyright 2024 EPAM Systems
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
117
package com.epam.reportportal.extension.slack;
218

319
import com.epam.reportportal.extension.CommonPluginCommand;
@@ -47,6 +63,7 @@
4763
import org.springframework.context.support.AbstractApplicationContext;
4864
import org.springframework.core.io.FileSystemResource;
4965
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
66+
import org.springframework.web.client.RestTemplate;
5067

5168
/**
5269
* @author Andrei Piankouski
@@ -100,6 +117,9 @@ public class SlackPluginExtension implements ReportPortalExtensionPoint, Disposa
100117
@Autowired
101118
private ProjectRepository projectRepository;
102119

120+
// @Autowired // uncomment for future release
121+
private final RestTemplate restTemplate = new RestTemplate();
122+
103123
@Autowired
104124
private ApplicationContext applicationContext;
105125

@@ -131,7 +151,7 @@ public SlackPluginExtension(Map<String, Object> initParams) {
131151

132152
launchFinishEventListenerSupplier = new MemoizingSupplier<>(
133153
() -> new SlackLaunchFinishEventListener(projectRepository,
134-
launchRepository, senderCaseMatcher.get(), attachmentResolverSupplier.get()));
154+
launchRepository, senderCaseMatcher.get(), attachmentResolverSupplier.get(), restTemplate));
135155
}
136156

137157
@PostConstruct

src/main/java/com/epam/reportportal/extension/slack/event/launch/SlackLaunchFinishEventListener.java

+9-13
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,23 @@
2727
import com.epam.ta.reportportal.entity.project.Project;
2828
import com.epam.ta.reportportal.entity.project.ProjectUtils;
2929
import com.epam.ta.reportportal.entity.project.email.SenderCase;
30-
import com.slack.api.Slack;
3130
import java.util.Map;
3231
import java.util.Optional;
3332
import org.apache.commons.lang3.BooleanUtils;
3433
import org.springframework.context.ApplicationListener;
34+
import org.springframework.web.client.RestTemplate;
3535

3636
/**
3737
* @author <a href="mailto:[email protected]">Andrei Piankouski</a>
3838
*/
3939
public class SlackLaunchFinishEventListener implements
4040
ApplicationListener<LaunchFinishedPluginEvent> {
4141

42-
private final static String SLACK_NOTIFICATION_ATTRIBUTE = "notifications.slack.enabled";
42+
public final static String SLACK_NOTIFICATION_ATTRIBUTE = "notifications.slack.enabled";
4343

44-
private final static String WEBHOOK_DETAILS = "webhookURL";
44+
public final static String WEBHOOK_DETAILS = "webhookURL";
4545

46-
private final static String PLUGIN_NOTIFICATION_TYPE = "slack";
46+
public final static String PLUGIN_NOTIFICATION_TYPE = "slack";
4747

4848
private final ProjectRepository projectRepository;
4949

@@ -52,15 +52,18 @@ public class SlackLaunchFinishEventListener implements
5252
private final SenderCaseMatcher senderCaseMatcher;
5353

5454
private final AttachmentResolver attachmentResolver;
55+
private final RestTemplate restTemplate;
5556

5657

5758
public SlackLaunchFinishEventListener(
5859
ProjectRepository projectRepository, LaunchRepository launchRepository,
59-
SenderCaseMatcher senderCaseMatcher, AttachmentResolver attachmentResolver) {
60+
SenderCaseMatcher senderCaseMatcher, AttachmentResolver attachmentResolver,
61+
RestTemplate restTemplate) {
6062
this.projectRepository = projectRepository;
6163
this.launchRepository = launchRepository;
6264
this.senderCaseMatcher = senderCaseMatcher;
6365
this.attachmentResolver = attachmentResolver;
66+
this.restTemplate = restTemplate;
6467
}
6568

6669
@Override
@@ -103,7 +106,7 @@ private void sendNotification(SenderCase senderCase, Launch launch, String launc
103106
Optional<String> webhookUrl = getWebhookUrl(senderCase);
104107
Optional<String> attachment = resolveAttachment(launch, launchLink);
105108
if (webhookUrl.isPresent() && attachment.isPresent()) {
106-
sendSlackNotification(webhookUrl.get(), attachment.get());
109+
restTemplate.postForLocation(webhookUrl.get(), attachment.get());
107110
}
108111
}
109112

@@ -116,13 +119,6 @@ private Optional<String> resolveAttachment(Launch launch, String launchLink) {
116119
return attachmentResolver.resolve(launch, launchLink);
117120
}
118121

119-
private void sendSlackNotification(String webhookUrl, String attachment) {
120-
try (Slack slack = Slack.getInstance()) {
121-
slack.send(webhookUrl, attachment);
122-
} catch (Exception e) {
123-
throw new ReportPortalException("Failed to send Slack notification", e);
124-
}
125-
}
126122

127123
private boolean isNotificationsEnabled(Project project) {
128124
Map<String, String> projectConfig = ProjectUtils.getConfigParameters(

src/main/resources/message-template/finish-launch.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,4 @@
204204
]
205205
}
206206
]
207-
}
207+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright 2024 EPAM Systems
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.epam.reportportal.extension.slack.event.launch;
18+
19+
import static com.epam.reportportal.extension.slack.utils.SampleAttachment.SAMPLE_ATTACHMENT;
20+
import static org.mockito.ArgumentMatchers.any;
21+
import static org.mockito.ArgumentMatchers.anyLong;
22+
import static org.mockito.ArgumentMatchers.anyString;
23+
import static org.mockito.Mockito.times;
24+
import static org.mockito.Mockito.verify;
25+
import static org.mockito.Mockito.when;
26+
27+
import com.epam.reportportal.extension.event.LaunchFinishedPluginEvent;
28+
import com.epam.reportportal.extension.slack.event.launch.resolver.AttachmentResolver;
29+
import com.epam.reportportal.extension.slack.event.launch.resolver.SenderCaseMatcher;
30+
import com.epam.reportportal.extension.slack.utils.MockData;
31+
import com.epam.ta.reportportal.dao.LaunchRepository;
32+
import com.epam.ta.reportportal.dao.ProjectRepository;
33+
import com.epam.ta.reportportal.entity.launch.Launch;
34+
import java.net.URI;
35+
import java.net.URISyntaxException;
36+
import java.util.Optional;
37+
import org.junit.jupiter.api.Disabled;
38+
import org.junit.jupiter.api.Test;
39+
import org.junit.jupiter.api.extension.ExtendWith;
40+
import org.mockito.Answers;
41+
import org.mockito.Mock;
42+
import org.mockito.junit.jupiter.MockitoExtension;
43+
import org.springframework.web.client.RestTemplate;
44+
45+
/**
46+
* @author <a href="mailto:[email protected]">Siarhei Hrabko</a>
47+
*/
48+
@ExtendWith(MockitoExtension.class)
49+
class SlackLaunchFinishEventListenerTest {
50+
51+
private static final String LAUNCH_LINK = "http://localhost:8080/ui/#admin123/launches/all/55";
52+
53+
@Mock
54+
RestTemplate restTemplate;// = new RestTemplate();
55+
@Mock
56+
ProjectRepository projectRepository;
57+
@Mock
58+
LaunchRepository launchRepository;
59+
@Mock(answer = Answers.CALLS_REAL_METHODS)
60+
SenderCaseMatcher senderCaseMatcher;
61+
@Mock
62+
AttachmentResolver attachmentResolver;
63+
64+
@Test
65+
@Disabled("until RestTemplate initialization in SlackPluginExtension switched to @Autowired")
66+
void sendNotificationPositive() throws URISyntaxException {
67+
var slackLaunchFinishEventListener = new SlackLaunchFinishEventListener(projectRepository,
68+
launchRepository, senderCaseMatcher, attachmentResolver, restTemplate);
69+
70+
when(projectRepository.findById(anyLong()))
71+
.thenReturn(Optional.of(MockData.getProjectSample()));
72+
when(launchRepository.findById(anyLong()))
73+
.thenReturn(Optional.of(MockData.getLaunch()));
74+
when(attachmentResolver.resolve(any(Launch.class), anyString()))
75+
.thenReturn(Optional.of(SAMPLE_ATTACHMENT));
76+
when(restTemplate.postForLocation(anyString(), anyString()))
77+
.thenReturn(new URI("http://localhost:8080"));
78+
79+
slackLaunchFinishEventListener.onApplicationEvent(
80+
new LaunchFinishedPluginEvent(1L, 10L, LAUNCH_LINK));
81+
82+
verify(restTemplate, times(1)).postForLocation(anyString(), anyString());
83+
84+
}
85+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright 2024 EPAM Systems
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.epam.reportportal.extension.slack.utils;
18+
19+
import static com.epam.reportportal.extension.slack.event.launch.SlackLaunchFinishEventListener.PLUGIN_NOTIFICATION_TYPE;
20+
import static com.epam.reportportal.extension.slack.event.launch.SlackLaunchFinishEventListener.SLACK_NOTIFICATION_ATTRIBUTE;
21+
import static com.epam.reportportal.extension.slack.event.launch.SlackLaunchFinishEventListener.WEBHOOK_DETAILS;
22+
import static com.epam.ta.reportportal.entity.enums.ProjectAttributeEnum.NOTIFICATIONS_ENABLED;
23+
24+
import com.epam.ta.reportportal.entity.attribute.Attribute;
25+
import com.epam.ta.reportportal.entity.enums.SendCase;
26+
import com.epam.ta.reportportal.entity.launch.Launch;
27+
import com.epam.ta.reportportal.entity.project.Project;
28+
import com.epam.ta.reportportal.entity.project.ProjectAttribute;
29+
import com.epam.ta.reportportal.entity.project.email.SenderCase;
30+
import com.epam.ta.reportportal.entity.project.email.SenderCaseOptions;
31+
import java.io.IOException;
32+
import java.io.InputStream;
33+
import java.nio.charset.StandardCharsets;
34+
import java.nio.file.Files;
35+
import java.nio.file.Paths;
36+
import java.util.Collections;
37+
import java.util.Map;
38+
import java.util.Set;
39+
import java.util.stream.Stream;
40+
import org.apache.commons.io.IOUtils;
41+
42+
public class MockData {
43+
44+
private static final String LAUNCH_NAME_1 = "Launch name 1";
45+
46+
public static Project getProjectSample() {
47+
var project = new Project();
48+
49+
project.setId(1L);
50+
project.setSenderCases(Collections.singleton(getSenderCase()));
51+
project.setProjectAttributes(getProjectAttributes());
52+
return project;
53+
}
54+
55+
private static Set<ProjectAttribute> getProjectAttributes() {
56+
var attribute1 = new Attribute();
57+
attribute1.setId(13L);
58+
attribute1.setName(NOTIFICATIONS_ENABLED.getAttribute());
59+
60+
var attribute2 = new Attribute();
61+
attribute2.setId(21L);
62+
attribute2.setName(SLACK_NOTIFICATION_ATTRIBUTE);
63+
64+
ProjectAttribute projectAttribute1 = new ProjectAttribute()
65+
.withAttribute(attribute1)
66+
.withProject(new Project())
67+
.withValue("true");
68+
69+
ProjectAttribute projectAttribute2 = new ProjectAttribute()
70+
.withAttribute(attribute2)
71+
.withProject(new Project())
72+
.withValue("true");
73+
74+
return Set.of(projectAttribute1, projectAttribute2);
75+
76+
}
77+
78+
79+
public static SenderCase getSenderCase() {
80+
var senderCase = new SenderCase();
81+
senderCase.setEnabled(true);
82+
senderCase.setType(PLUGIN_NOTIFICATION_TYPE);
83+
senderCase.setSendCase(SendCase.ALWAYS);
84+
senderCase.setLaunchNames(Set.of(LAUNCH_NAME_1));
85+
senderCase.setRuleDetails(getSenderCaseOptions());
86+
return senderCase;
87+
}
88+
89+
public static Launch getLaunch() {
90+
var launch = new Launch();
91+
launch.setId(20L);
92+
launch.setName(LAUNCH_NAME_1);
93+
return launch;
94+
}
95+
96+
public static SenderCaseOptions getSenderCaseOptions() {
97+
SenderCaseOptions senderCaseOptions = new SenderCaseOptions();
98+
senderCaseOptions.setOptions(
99+
Map.of(WEBHOOK_DETAILS,
100+
"https://hooks.slack.com/services/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"));
101+
return senderCaseOptions;
102+
}
103+
104+
public static String readFileToString(String path) throws IOException {
105+
106+
try (InputStream resourceAsStream = MockData.class.getClassLoader().getResourceAsStream(path)) {
107+
if (resourceAsStream != null) {
108+
return IOUtils.toString(resourceAsStream, StandardCharsets.UTF_8);
109+
} else {
110+
StringBuilder sb = new StringBuilder();
111+
try (Stream<String> lines = Files.lines(Paths.get(path))) {
112+
lines.forEach(sb::append);
113+
}
114+
return sb.toString();
115+
}
116+
}
117+
}
118+
}
119+

0 commit comments

Comments
 (0)