Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EPMRPP-97593 update dependencies. add unit test #9

Merged
merged 3 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ dependencyManagement {
}
}

ext['junit-jupiter.version'] = "${junitVersion}"

dependencies {
if (releaseMode) {
implementation 'com.epam.reportportal:commons-dao'
Expand All @@ -49,12 +51,19 @@ dependencies {
annotationProcessor 'com.github.reportportal:plugin-api:develop-SNAPSHOT'
}

implementation("com.slack.api:slack-api-client:1.27.1") {
exclude group: "org.slf4j"
}
compileOnly "org.projectlombok:lombok:${lombokVersion}"
annotationProcessor "org.projectlombok:lombok:${lombokVersion}"
testCompileOnly "org.projectlombok:lombok:${lombokVersion}"
testAnnotationProcessor "org.projectlombok:lombok:${lombokVersion}"

implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'org.hibernate:hibernate-core:5.6.15.Final'
testImplementation 'org.mockito:mockito-core:5.14.2'
testImplementation 'org.mockito:mockito-junit-jupiter:5.14.2'
testImplementation "org.junit.jupiter:junit-jupiter"
testImplementation "org.junit.jupiter:junit-jupiter-api"
testImplementation "org.junit.jupiter:junit-jupiter-engine"
testImplementation 'net.bytebuddy:byte-buddy:1.14.9'
}

test {
Expand Down Expand Up @@ -115,6 +124,7 @@ shadowJar {
configurations = [project.configurations.compileClasspath]
zip64 true
dependencies {
include(dependency('commons-io:commons-io:2.15.1'))
}
}

Expand Down
2 changes: 2 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
version=1.0.0
description=EPAM Report Portal. Slack plugin.
pluginId = slack
lombokVersion=1.18.36
junitVersion=5.11.0
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright 2024 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.epam.reportportal.extension.slack;

import com.epam.reportportal.extension.CommonPluginCommand;
Expand Down Expand Up @@ -47,6 +63,7 @@
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.io.FileSystemResource;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.web.client.RestTemplate;

/**
* @author Andrei Piankouski
Expand Down Expand Up @@ -100,6 +117,9 @@ public class SlackPluginExtension implements ReportPortalExtensionPoint, Disposa
@Autowired
private ProjectRepository projectRepository;

// @Autowired // uncomment for future release
private final RestTemplate restTemplate = new RestTemplate();

@Autowired
private ApplicationContext applicationContext;

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

launchFinishEventListenerSupplier = new MemoizingSupplier<>(
() -> new SlackLaunchFinishEventListener(projectRepository,
launchRepository, senderCaseMatcher.get(), attachmentResolverSupplier.get()));
launchRepository, senderCaseMatcher.get(), attachmentResolverSupplier.get(), restTemplate));
}

@PostConstruct
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,23 @@
import com.epam.ta.reportportal.entity.project.Project;
import com.epam.ta.reportportal.entity.project.ProjectUtils;
import com.epam.ta.reportportal.entity.project.email.SenderCase;
import com.slack.api.Slack;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.context.ApplicationListener;
import org.springframework.web.client.RestTemplate;

/**
* @author <a href="mailto:andrei_piankouski@epam.com">Andrei Piankouski</a>
*/
public class SlackLaunchFinishEventListener implements
ApplicationListener<LaunchFinishedPluginEvent> {

private final static String SLACK_NOTIFICATION_ATTRIBUTE = "notifications.slack.enabled";
public final static String SLACK_NOTIFICATION_ATTRIBUTE = "notifications.slack.enabled";

private final static String WEBHOOK_DETAILS = "webhookURL";
public final static String WEBHOOK_DETAILS = "webhookURL";

private final static String PLUGIN_NOTIFICATION_TYPE = "slack";
public final static String PLUGIN_NOTIFICATION_TYPE = "slack";

private final ProjectRepository projectRepository;

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

private final AttachmentResolver attachmentResolver;
private final RestTemplate restTemplate;


public SlackLaunchFinishEventListener(
ProjectRepository projectRepository, LaunchRepository launchRepository,
SenderCaseMatcher senderCaseMatcher, AttachmentResolver attachmentResolver) {
SenderCaseMatcher senderCaseMatcher, AttachmentResolver attachmentResolver,
RestTemplate restTemplate) {
this.projectRepository = projectRepository;
this.launchRepository = launchRepository;
this.senderCaseMatcher = senderCaseMatcher;
this.attachmentResolver = attachmentResolver;
this.restTemplate = restTemplate;
}

@Override
Expand Down Expand Up @@ -103,7 +106,7 @@ private void sendNotification(SenderCase senderCase, Launch launch, String launc
Optional<String> webhookUrl = getWebhookUrl(senderCase);
Optional<String> attachment = resolveAttachment(launch, launchLink);
if (webhookUrl.isPresent() && attachment.isPresent()) {
sendSlackNotification(webhookUrl.get(), attachment.get());
restTemplate.postForLocation(webhookUrl.get(), attachment.get());
}
}

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

private void sendSlackNotification(String webhookUrl, String attachment) {
try (Slack slack = Slack.getInstance()) {
slack.send(webhookUrl, attachment);
} catch (Exception e) {
throw new ReportPortalException("Failed to send Slack notification", e);
}
}

private boolean isNotificationsEnabled(Project project) {
Map<String, String> projectConfig = ProjectUtils.getConfigParameters(
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/message-template/finish-launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -204,4 +204,4 @@
]
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright 2024 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.epam.reportportal.extension.slack.event.launch;

import static com.epam.reportportal.extension.slack.utils.SampleAttachment.SAMPLE_ATTACHMENT;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.epam.reportportal.extension.event.LaunchFinishedPluginEvent;
import com.epam.reportportal.extension.slack.event.launch.resolver.AttachmentResolver;
import com.epam.reportportal.extension.slack.event.launch.resolver.SenderCaseMatcher;
import com.epam.reportportal.extension.slack.utils.MockData;
import com.epam.ta.reportportal.dao.LaunchRepository;
import com.epam.ta.reportportal.dao.ProjectRepository;
import com.epam.ta.reportportal.entity.launch.Launch;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Optional;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.web.client.RestTemplate;

/**
* @author <a href="mailto:siarhei_hrabko@epam.com">Siarhei Hrabko</a>
*/
@ExtendWith(MockitoExtension.class)
class SlackLaunchFinishEventListenerTest {

private static final String LAUNCH_LINK = "http://localhost:8080/ui/#admin123/launches/all/55";

@Mock
RestTemplate restTemplate;// = new RestTemplate();
@Mock
ProjectRepository projectRepository;
@Mock
LaunchRepository launchRepository;
@Mock(answer = Answers.CALLS_REAL_METHODS)
SenderCaseMatcher senderCaseMatcher;
@Mock
AttachmentResolver attachmentResolver;

@Test
@Disabled("until RestTemplate initialization in SlackPluginExtension switched to @Autowired")
void sendNotificationPositive() throws URISyntaxException {
var slackLaunchFinishEventListener = new SlackLaunchFinishEventListener(projectRepository,
launchRepository, senderCaseMatcher, attachmentResolver, restTemplate);

when(projectRepository.findById(anyLong()))
.thenReturn(Optional.of(MockData.getProjectSample()));
when(launchRepository.findById(anyLong()))
.thenReturn(Optional.of(MockData.getLaunch()));
when(attachmentResolver.resolve(any(Launch.class), anyString()))
.thenReturn(Optional.of(SAMPLE_ATTACHMENT));
when(restTemplate.postForLocation(anyString(), anyString()))
.thenReturn(new URI("http://localhost:8080"));

slackLaunchFinishEventListener.onApplicationEvent(
new LaunchFinishedPluginEvent(1L, 10L, LAUNCH_LINK));

verify(restTemplate, times(1)).postForLocation(anyString(), anyString());

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright 2024 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.epam.reportportal.extension.slack.utils;

import static com.epam.reportportal.extension.slack.event.launch.SlackLaunchFinishEventListener.PLUGIN_NOTIFICATION_TYPE;
import static com.epam.reportportal.extension.slack.event.launch.SlackLaunchFinishEventListener.SLACK_NOTIFICATION_ATTRIBUTE;
import static com.epam.reportportal.extension.slack.event.launch.SlackLaunchFinishEventListener.WEBHOOK_DETAILS;
import static com.epam.ta.reportportal.entity.enums.ProjectAttributeEnum.NOTIFICATIONS_ENABLED;

import com.epam.ta.reportportal.entity.attribute.Attribute;
import com.epam.ta.reportportal.entity.enums.SendCase;
import com.epam.ta.reportportal.entity.launch.Launch;
import com.epam.ta.reportportal.entity.project.Project;
import com.epam.ta.reportportal.entity.project.ProjectAttribute;
import com.epam.ta.reportportal.entity.project.email.SenderCase;
import com.epam.ta.reportportal.entity.project.email.SenderCaseOptions;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
import org.apache.commons.io.IOUtils;

public class MockData {

private static final String LAUNCH_NAME_1 = "Launch name 1";

public static Project getProjectSample() {
var project = new Project();

project.setId(1L);
project.setSenderCases(Collections.singleton(getSenderCase()));
project.setProjectAttributes(getProjectAttributes());
return project;
}

private static Set<ProjectAttribute> getProjectAttributes() {
var attribute1 = new Attribute();
attribute1.setId(13L);
attribute1.setName(NOTIFICATIONS_ENABLED.getAttribute());

var attribute2 = new Attribute();
attribute2.setId(21L);
attribute2.setName(SLACK_NOTIFICATION_ATTRIBUTE);

ProjectAttribute projectAttribute1 = new ProjectAttribute()
.withAttribute(attribute1)
.withProject(new Project())
.withValue("true");

ProjectAttribute projectAttribute2 = new ProjectAttribute()
.withAttribute(attribute2)
.withProject(new Project())
.withValue("true");

return Set.of(projectAttribute1, projectAttribute2);

}


public static SenderCase getSenderCase() {
var senderCase = new SenderCase();
senderCase.setEnabled(true);
senderCase.setType(PLUGIN_NOTIFICATION_TYPE);
senderCase.setSendCase(SendCase.ALWAYS);
senderCase.setLaunchNames(Set.of(LAUNCH_NAME_1));
senderCase.setRuleDetails(getSenderCaseOptions());
return senderCase;
}

public static Launch getLaunch() {
var launch = new Launch();
launch.setId(20L);
launch.setName(LAUNCH_NAME_1);
return launch;
}

public static SenderCaseOptions getSenderCaseOptions() {
SenderCaseOptions senderCaseOptions = new SenderCaseOptions();
senderCaseOptions.setOptions(
Map.of(WEBHOOK_DETAILS,
"https://hooks.slack.com/services/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"));
return senderCaseOptions;
}

public static String readFileToString(String path) throws IOException {

try (InputStream resourceAsStream = MockData.class.getClassLoader().getResourceAsStream(path)) {
if (resourceAsStream != null) {
return IOUtils.toString(resourceAsStream, StandardCharsets.UTF_8);
} else {
StringBuilder sb = new StringBuilder();
try (Stream<String> lines = Files.lines(Paths.get(path))) {
lines.forEach(sb::append);
}
return sb.toString();
}
}
}
}

Loading
Loading