From b2c785bf73a1847d299e8e544391d409be501b9e Mon Sep 17 00:00:00 2001 From: whiskels Date: Thu, 5 Jun 2025 21:46:02 +0300 Subject: [PATCH] T-39: add additional sink for reports --- README.md | 4 +- docker-compose.yml | 4 +- src/main/java/com/whiskels/notifier/App.java | 2 + .../config/clock/ClockConfiguration.java | 8 + .../infrastructure/report/ReportExecutor.java | 8 + .../{ => report}/slack/SlackClient.java | 2 +- .../report/slack/SlackPayloadMapper.java | 33 +++ .../report/slack/SlackReportExecutor.java | 33 +++ .../slack/builder/AccessoryBlock.java | 2 +- .../slack/builder/SlackPayloadBuilder.java | 4 +- .../slack/config/SlackConfiguration.java | 2 +- .../report/webhook/FeignWebhookSink.java | 14 + .../webhook/FeignWebhookSinkConfig.java | 22 ++ .../report/webhook/FeignWebhookSinkDto.java | 8 + .../report/webhook/WebhookSinkExecutor.java | 42 +++ .../ScheduledReportTaskSubmitter.java | 14 +- .../reporting/SlackPayloadExecutor.java | 23 -- .../notifier/reporting/_ReportConfig.java | 39 ++- .../service/GenericReportService.java | 3 +- .../notifier/reporting/service/Report.java | 36 +++ .../service/ReportMessageConverter.java | 4 +- .../reporting/service/ReportServiceImpl.java | 15 +- .../reporting/service/SimpleReport.java | 14 - ...merBirthdayInfoReportMessageConverter.java | 14 +- .../CustomerDebtReportMessageConverter.java | 28 +- .../PaymentReportMessageConverter.java | 15 +- .../EmployeeEventReportMessageConverter.java | 25 +- .../utilities/collections/StreamUtil.java | 8 +- src/main/resources/application-mock.yaml | 26 +- src/main/resources/application-prod.yaml | 13 +- .../infrastructure/slack/SlackClientTest.java | 1 + .../builder/SlackPayloadBuilderTest.java | 1 + .../reporting/GenericReportServiceTest.java | 8 +- .../reporting/ReportPropertiesTest.java | 6 +- .../notifier/reporting/ReportServiceTest.java | 12 +- .../notifier/reporting/ReportTest.java | 36 +++ .../notifier/reporting/SimpleReportTest.java | 36 --- ...Test.java => SlackReportExecutorTest.java} | 32 ++- ...irthdayInfoReportMessageConverterTest.java | 119 ++------- ...st.java => BeforeEventReportDataTest.java} | 6 +- ...textTest.java => DailyReportDataTest.java} | 6 +- ...st.java => MonthMiddleReportDataTest.java} | 6 +- ...est.java => MonthStartReportDataTest.java} | 6 +- ...ustomerDebtReportMessageConverterTest.java | 245 +++++------------- .../PaymentReportMessageConverterTest.java | 121 ++------- ...ployeeEventReportMessageConverterTest.java | 165 ++---------- ...st.java => BeforeEventReportDataTest.java} | 3 +- ...textTest.java => DailyReportDataTest.java} | 2 +- ...st.java => MonthMiddleReportDataTest.java} | 2 +- ...est.java => MonthStartReportDataTest.java} | 2 +- .../fetch/EmployeeDataFetchServiceTest.java | 2 - 51 files changed, 546 insertions(+), 736 deletions(-) create mode 100644 src/main/java/com/whiskels/notifier/infrastructure/report/ReportExecutor.java rename src/main/java/com/whiskels/notifier/infrastructure/{ => report}/slack/SlackClient.java (91%) create mode 100644 src/main/java/com/whiskels/notifier/infrastructure/report/slack/SlackPayloadMapper.java create mode 100644 src/main/java/com/whiskels/notifier/infrastructure/report/slack/SlackReportExecutor.java rename src/main/java/com/whiskels/notifier/infrastructure/{ => report}/slack/builder/AccessoryBlock.java (86%) rename src/main/java/com/whiskels/notifier/infrastructure/{ => report}/slack/builder/SlackPayloadBuilder.java (94%) rename src/main/java/com/whiskels/notifier/infrastructure/{ => report}/slack/config/SlackConfiguration.java (81%) create mode 100644 src/main/java/com/whiskels/notifier/infrastructure/report/webhook/FeignWebhookSink.java create mode 100644 src/main/java/com/whiskels/notifier/infrastructure/report/webhook/FeignWebhookSinkConfig.java create mode 100644 src/main/java/com/whiskels/notifier/infrastructure/report/webhook/FeignWebhookSinkDto.java create mode 100644 src/main/java/com/whiskels/notifier/infrastructure/report/webhook/WebhookSinkExecutor.java delete mode 100644 src/main/java/com/whiskels/notifier/reporting/SlackPayloadExecutor.java create mode 100644 src/main/java/com/whiskels/notifier/reporting/service/Report.java delete mode 100644 src/main/java/com/whiskels/notifier/reporting/service/SimpleReport.java create mode 100644 src/test/java/com/whiskels/notifier/reporting/ReportTest.java delete mode 100644 src/test/java/com/whiskels/notifier/reporting/SimpleReportTest.java rename src/test/java/com/whiskels/notifier/reporting/executor/{SlackPayloadExecutorTest.java => SlackReportExecutorTest.java} (51%) rename src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/{BeforeEventReportContextTest.java => BeforeEventReportDataTest.java} (87%) rename src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/{DailyReportContextTest.java => DailyReportDataTest.java} (87%) rename src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/{MonthMiddleReportContextTest.java => MonthMiddleReportDataTest.java} (90%) rename src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/{MonthStartReportContextTest.java => MonthStartReportDataTest.java} (91%) rename src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/{BeforeEventReportContextTest.java => BeforeEventReportDataTest.java} (92%) rename src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/{DailyReportContextTest.java => DailyReportDataTest.java} (98%) rename src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/{MonthMiddleReportContextTest.java => MonthMiddleReportDataTest.java} (98%) rename src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/{MonthStartReportContextTest.java => MonthStartReportDataTest.java} (98%) diff --git a/README.md b/README.md index d51e0fe5..4bc4853c 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Then run docker-compose with environment variables ```console TELEGRAM_BOT_TOKEN=${YOUR_TOKEN} \ TELEGRAM_BOT_ADMIN=${YOUR_TELEGRAM_ID} \ -SLACK_WEBHOOK=${SLACK_WEBHOOK} \ +WEBHOOK_URL=${WEBHOOK_URL} \ docker-compose up ``` @@ -51,7 +51,7 @@ Adjust application-mock with report.parameters.schedule to send reports to slack Adjust SPRING_PROFILES_ACTIVE in docker-compose to "mock" and run docker-compose with your webhook ```console -SLACK_WEBHOOK=${SLACK_WEBHOOK} \ +WEBHOOK_URL=${WEBHOOK_URL} \ docker-compose up ``` diff --git a/docker-compose.yml b/docker-compose.yml index 124753da..ad79f2d7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ services: - db environment: - SPRING_PROFILES_ACTIVE=mock,telegram - - SLACK_WEBHOOK + - WEBHOOK_URL - TELEGRAM_BOT_ADMIN - TELEGRAM_BOT_TOKEN - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/postgres @@ -20,6 +20,8 @@ services: db: image: 'postgres:16.2' container_name: db + ports: + - "5432:5432" environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres \ No newline at end of file diff --git a/src/main/java/com/whiskels/notifier/App.java b/src/main/java/com/whiskels/notifier/App.java index dd49d80a..a7ea4b0e 100644 --- a/src/main/java/com/whiskels/notifier/App.java +++ b/src/main/java/com/whiskels/notifier/App.java @@ -2,6 +2,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Profile; import org.springframework.scheduling.annotation.EnableScheduling; @@ -10,6 +11,7 @@ @SpringBootApplication @EnableFeignClients @EnableScheduling +@EnableConfigurationProperties public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); diff --git a/src/main/java/com/whiskels/notifier/infrastructure/config/clock/ClockConfiguration.java b/src/main/java/com/whiskels/notifier/infrastructure/config/clock/ClockConfiguration.java index 4dec9468..89316503 100644 --- a/src/main/java/com/whiskels/notifier/infrastructure/config/clock/ClockConfiguration.java +++ b/src/main/java/com/whiskels/notifier/infrastructure/config/clock/ClockConfiguration.java @@ -6,13 +6,21 @@ import org.springframework.context.annotation.Profile; import java.time.Clock; +import java.time.Instant; import java.time.ZoneId; @Configuration @Profile("!test") class ClockConfiguration { @Bean + @Profile("!mock") Clock defaultClock(@Value("${common.timezone}") String timeZone) { return Clock.system(ZoneId.of(timeZone)); } + + @Bean + @Profile("mock") + Clock mockedClock() { + return Clock.fixed(Instant.parse("2025-01-01T10:15:30Z"), ZoneId.of("UTC")); + } } diff --git a/src/main/java/com/whiskels/notifier/infrastructure/report/ReportExecutor.java b/src/main/java/com/whiskels/notifier/infrastructure/report/ReportExecutor.java new file mode 100644 index 00000000..5196a8bf --- /dev/null +++ b/src/main/java/com/whiskels/notifier/infrastructure/report/ReportExecutor.java @@ -0,0 +1,8 @@ +package com.whiskels.notifier.infrastructure.report; + +import com.whiskels.notifier.reporting.ReportType; +import com.whiskels.notifier.reporting.service.Report; + +public interface ReportExecutor { + void send(ReportType type, Report report); +} diff --git a/src/main/java/com/whiskels/notifier/infrastructure/slack/SlackClient.java b/src/main/java/com/whiskels/notifier/infrastructure/report/slack/SlackClient.java similarity index 91% rename from src/main/java/com/whiskels/notifier/infrastructure/slack/SlackClient.java rename to src/main/java/com/whiskels/notifier/infrastructure/report/slack/SlackClient.java index 5cbc0867..06f7575f 100644 --- a/src/main/java/com/whiskels/notifier/infrastructure/slack/SlackClient.java +++ b/src/main/java/com/whiskels/notifier/infrastructure/report/slack/SlackClient.java @@ -1,4 +1,4 @@ -package com.whiskels.notifier.infrastructure.slack; +package com.whiskels.notifier.infrastructure.report.slack; import com.slack.api.Slack; import com.slack.api.webhook.Payload; diff --git a/src/main/java/com/whiskels/notifier/infrastructure/report/slack/SlackPayloadMapper.java b/src/main/java/com/whiskels/notifier/infrastructure/report/slack/SlackPayloadMapper.java new file mode 100644 index 00000000..bcad4458 --- /dev/null +++ b/src/main/java/com/whiskels/notifier/infrastructure/report/slack/SlackPayloadMapper.java @@ -0,0 +1,33 @@ +package com.whiskels.notifier.infrastructure.report.slack; + +import com.slack.api.webhook.Payload; +import com.whiskels.notifier.infrastructure.report.slack.builder.SlackPayloadBuilder; +import com.whiskels.notifier.reporting.service.Report; +import org.springframework.stereotype.Service; + +import static java.util.Objects.nonNull; + +@Service +public class SlackPayloadMapper { + public Payload map(final Report report) { + var builder = SlackPayloadBuilder.builder() + .header(report.getHeader()); + if (report.isNotifyChannel()) { + builder.notifyChannel(); + } + + if (nonNull(report.getBanner())) { + builder.header(report.getBanner()); + } + + report.getBody().forEach(block -> { + if (nonNull(block.mediaContentUrl())) { + builder.block(block.text(), block.mediaContentUrl()); + } else { + builder.block(block.text()); + } + }); + + return builder.build(); + } +} diff --git a/src/main/java/com/whiskels/notifier/infrastructure/report/slack/SlackReportExecutor.java b/src/main/java/com/whiskels/notifier/infrastructure/report/slack/SlackReportExecutor.java new file mode 100644 index 00000000..48baa1c5 --- /dev/null +++ b/src/main/java/com/whiskels/notifier/infrastructure/report/slack/SlackReportExecutor.java @@ -0,0 +1,33 @@ +package com.whiskels.notifier.infrastructure.report.slack; + +import com.whiskels.notifier.infrastructure.report.ReportExecutor; +import com.whiskels.notifier.reporting.ReportType; +import com.whiskels.notifier.reporting.service.Report; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.util.Map; + +import static org.springframework.util.CollectionUtils.isEmpty; + +@Slf4j +@AllArgsConstructor +public class SlackReportExecutor implements ReportExecutor { + private final SlackClient slackClient; + private final SlackPayloadMapper slackPayloadMapper; + private final Map webhookMappings; + + @Override + public void send(ReportType type, Report report) { + if (isEmpty(webhookMappings) || !webhookMappings.containsKey(type)) { + log.error("No webhook mapping for type {}", type); + return; + } + try { + slackClient.send(webhookMappings.get(type), slackPayloadMapper.map(report)); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } +} diff --git a/src/main/java/com/whiskels/notifier/infrastructure/slack/builder/AccessoryBlock.java b/src/main/java/com/whiskels/notifier/infrastructure/report/slack/builder/AccessoryBlock.java similarity index 86% rename from src/main/java/com/whiskels/notifier/infrastructure/slack/builder/AccessoryBlock.java rename to src/main/java/com/whiskels/notifier/infrastructure/report/slack/builder/AccessoryBlock.java index 00b1071e..986e3177 100644 --- a/src/main/java/com/whiskels/notifier/infrastructure/slack/builder/AccessoryBlock.java +++ b/src/main/java/com/whiskels/notifier/infrastructure/report/slack/builder/AccessoryBlock.java @@ -1,4 +1,4 @@ -package com.whiskels.notifier.infrastructure.slack.builder; +package com.whiskels.notifier.infrastructure.report.slack.builder; import com.slack.api.model.block.element.BlockElement; import lombok.Data; diff --git a/src/main/java/com/whiskels/notifier/infrastructure/slack/builder/SlackPayloadBuilder.java b/src/main/java/com/whiskels/notifier/infrastructure/report/slack/builder/SlackPayloadBuilder.java similarity index 94% rename from src/main/java/com/whiskels/notifier/infrastructure/slack/builder/SlackPayloadBuilder.java rename to src/main/java/com/whiskels/notifier/infrastructure/report/slack/builder/SlackPayloadBuilder.java index 979d2397..afb4940f 100644 --- a/src/main/java/com/whiskels/notifier/infrastructure/slack/builder/SlackPayloadBuilder.java +++ b/src/main/java/com/whiskels/notifier/infrastructure/report/slack/builder/SlackPayloadBuilder.java @@ -1,4 +1,4 @@ -package com.whiskels.notifier.infrastructure.slack.builder; +package com.whiskels.notifier.infrastructure.report.slack.builder; import com.slack.api.model.block.HeaderBlock; import com.slack.api.model.block.LayoutBlock; @@ -54,7 +54,7 @@ public SlackPayloadBuilder block(String text) { return this; } - public SlackPayloadBuilder block(String text, String picUrl) { + public SlackPayloadBuilder block(String text, String picUrl) { MarkdownTextObject content = new MarkdownTextObject(); content.setText(text); diff --git a/src/main/java/com/whiskels/notifier/infrastructure/slack/config/SlackConfiguration.java b/src/main/java/com/whiskels/notifier/infrastructure/report/slack/config/SlackConfiguration.java similarity index 81% rename from src/main/java/com/whiskels/notifier/infrastructure/slack/config/SlackConfiguration.java rename to src/main/java/com/whiskels/notifier/infrastructure/report/slack/config/SlackConfiguration.java index 5fb89166..0e8cd074 100644 --- a/src/main/java/com/whiskels/notifier/infrastructure/slack/config/SlackConfiguration.java +++ b/src/main/java/com/whiskels/notifier/infrastructure/report/slack/config/SlackConfiguration.java @@ -1,4 +1,4 @@ -package com.whiskels.notifier.infrastructure.slack.config; +package com.whiskels.notifier.infrastructure.report.slack.config; import com.slack.api.Slack; import org.springframework.context.annotation.Bean; diff --git a/src/main/java/com/whiskels/notifier/infrastructure/report/webhook/FeignWebhookSink.java b/src/main/java/com/whiskels/notifier/infrastructure/report/webhook/FeignWebhookSink.java new file mode 100644 index 00000000..590215cc --- /dev/null +++ b/src/main/java/com/whiskels/notifier/infrastructure/report/webhook/FeignWebhookSink.java @@ -0,0 +1,14 @@ +package com.whiskels.notifier.infrastructure.report.webhook; + +import feign.Headers; +import feign.RequestLine; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestBody; + +import java.net.URI; + +public interface FeignWebhookSink { + @RequestLine("POST") + @Headers("Content-Type: application/json") + ResponseEntity send(URI url, @RequestBody FeignWebhookSinkDto dto); +} diff --git a/src/main/java/com/whiskels/notifier/infrastructure/report/webhook/FeignWebhookSinkConfig.java b/src/main/java/com/whiskels/notifier/infrastructure/report/webhook/FeignWebhookSinkConfig.java new file mode 100644 index 00000000..d523b27a --- /dev/null +++ b/src/main/java/com/whiskels/notifier/infrastructure/report/webhook/FeignWebhookSinkConfig.java @@ -0,0 +1,22 @@ +package com.whiskels.notifier.infrastructure.report.webhook; + +import feign.Feign; +import feign.Target; +import feign.codec.Decoder; +import feign.codec.Encoder; +import org.springframework.cloud.openfeign.FeignClientsConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import(FeignClientsConfiguration.class) +class FeignWebhookSinkConfig { + @Bean + FeignWebhookSink feignWebhookSink(Encoder encoder, Decoder decoder) { + return Feign.builder() + .encoder(encoder) + .decoder(decoder) + .target(Target.EmptyTarget.create(FeignWebhookSink.class)); + } +} diff --git a/src/main/java/com/whiskels/notifier/infrastructure/report/webhook/FeignWebhookSinkDto.java b/src/main/java/com/whiskels/notifier/infrastructure/report/webhook/FeignWebhookSinkDto.java new file mode 100644 index 00000000..9bb4f9de --- /dev/null +++ b/src/main/java/com/whiskels/notifier/infrastructure/report/webhook/FeignWebhookSinkDto.java @@ -0,0 +1,8 @@ +package com.whiskels.notifier.infrastructure.report.webhook; + +import lombok.Data; + +@Data +public class FeignWebhookSinkDto { + String message; +} diff --git a/src/main/java/com/whiskels/notifier/infrastructure/report/webhook/WebhookSinkExecutor.java b/src/main/java/com/whiskels/notifier/infrastructure/report/webhook/WebhookSinkExecutor.java new file mode 100644 index 00000000..e46a3336 --- /dev/null +++ b/src/main/java/com/whiskels/notifier/infrastructure/report/webhook/WebhookSinkExecutor.java @@ -0,0 +1,42 @@ +package com.whiskels.notifier.infrastructure.report.webhook; + +import com.whiskels.notifier.infrastructure.report.ReportExecutor; +import com.whiskels.notifier.reporting.ReportType; +import com.whiskels.notifier.reporting.service.Report; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; + +import java.net.URI; +import java.util.Map; + +import static com.whiskels.notifier.utilities.formatters.StringFormatter.COLLECTOR_NEW_LINE; + +@Slf4j +@RequiredArgsConstructor +public class WebhookSinkExecutor implements ReportExecutor { + private final FeignWebhookSink feignWebhookSink; + private final Map webhookMappings; + + @Override + public void send(final ReportType type, final Report report) { + if (CollectionUtils.isEmpty(webhookMappings) || !webhookMappings.containsKey(type)) { + log.error("No webhook mapping for type {}", type); + return; + } + try { + final var dto = new FeignWebhookSinkDto(); + var reportBody = report.getBody().stream() + .map(Report.ReportBodyBlock::text) + .collect(COLLECTOR_NEW_LINE); + dto.setMessage(STR."\{report.getHeader()}\n\n\{reportBody}"); + final var response = feignWebhookSink.send(new URI(webhookMappings.get(type)), dto); + + if (!response.getStatusCode().is2xxSuccessful()) { + log.error("Webhook sink {} failed: {}", type, response); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/com/whiskels/notifier/reporting/ScheduledReportTaskSubmitter.java b/src/main/java/com/whiskels/notifier/reporting/ScheduledReportTaskSubmitter.java index b9f3bca3..35073c2c 100644 --- a/src/main/java/com/whiskels/notifier/reporting/ScheduledReportTaskSubmitter.java +++ b/src/main/java/com/whiskels/notifier/reporting/ScheduledReportTaskSubmitter.java @@ -12,6 +12,7 @@ import java.util.Map; import java.util.TimeZone; +import static com.whiskels.notifier.utilities.formatters.StringFormatter.COLLECTOR_NEW_LINE; import static org.springframework.util.CollectionUtils.isEmpty; @RequiredArgsConstructor @@ -32,11 +33,16 @@ private void scheduleReports() { log.error("No cron triggers found for reports"); return; } + log.info("Scheduling reports: \n{}", + reportCronMap.entrySet().stream() + .map(entry -> String.format(" %-8s -> %s", entry.getKey(), entry.getValue())) + .collect(COLLECTOR_NEW_LINE)); + reportCronMap.forEach((type, cron) -> - executor.schedule(() -> service.executeReport(type), - new CronTrigger(cron, TimeZone.getTimeZone(ZoneId.of(timeZone)) - ) + executor.schedule(() -> service.executeReport(type), + new CronTrigger(cron, TimeZone.getTimeZone(ZoneId.of(timeZone)) ) - ); + ) + ); } } \ No newline at end of file diff --git a/src/main/java/com/whiskels/notifier/reporting/SlackPayloadExecutor.java b/src/main/java/com/whiskels/notifier/reporting/SlackPayloadExecutor.java deleted file mode 100644 index 2bd95a34..00000000 --- a/src/main/java/com/whiskels/notifier/reporting/SlackPayloadExecutor.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.whiskels.notifier.reporting; - -import com.slack.api.webhook.Payload; -import com.whiskels.notifier.infrastructure.slack.SlackClient; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import java.io.IOException; -import java.util.Map; - -@Slf4j -@AllArgsConstructor -public class SlackPayloadExecutor { - private final SlackClient slackClient; - private final Map webhookMappings; - - public void send(ReportType type, Payload payload) throws IOException { - if (!webhookMappings.containsKey(type)) { - throw new IllegalStateException(STR."No url found for report type=\{type}"); - } - slackClient.send(webhookMappings.get(type), payload); - } -} diff --git a/src/main/java/com/whiskels/notifier/reporting/_ReportConfig.java b/src/main/java/com/whiskels/notifier/reporting/_ReportConfig.java index 3f905658..2875e07b 100644 --- a/src/main/java/com/whiskels/notifier/reporting/_ReportConfig.java +++ b/src/main/java/com/whiskels/notifier/reporting/_ReportConfig.java @@ -1,8 +1,14 @@ package com.whiskels.notifier.reporting; -import com.whiskels.notifier.infrastructure.slack.SlackClient; +import com.whiskels.notifier.infrastructure.report.slack.SlackClient; +import com.whiskels.notifier.infrastructure.report.slack.SlackPayloadMapper; +import com.whiskels.notifier.infrastructure.report.slack.SlackReportExecutor; +import com.whiskels.notifier.infrastructure.report.webhook.FeignWebhookSink; +import com.whiskels.notifier.infrastructure.report.webhook.WebhookSinkExecutor; import com.whiskels.notifier.reporting.service.ReportServiceImpl; +import com.whiskels.notifier.utilities.collections.StreamUtil; import lombok.Getter; +import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -13,24 +19,42 @@ import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.annotation.EnableScheduling; +import javax.annotation.PostConstruct; import java.util.Map; +import static com.whiskels.notifier.utilities.formatters.StringFormatter.COLLECTOR_NEW_LINE; + @Configuration(proxyBeanMethods = false) @ConfigurationPropertiesScan @EnableScheduling @Slf4j +@RequiredArgsConstructor class _ReportConfig { + private final ReportProperties reportProperties; + + @PostConstruct + void logWebhookMappings() { + log.info("Report sink configuration: \n{}", reportProperties.getWebhooks().entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .map(entry -> String.format(" %-8s -> %s", entry.getKey(), StreamUtil.map(entry.getValue().entrySet(), Map.Entry::getKey))) + .collect(COLLECTOR_NEW_LINE)); + } + @Bean ScheduledReportTaskSubmitter scheduledReportTaskSubmitter(TaskScheduler taskScheduler, - ReportProperties reportProperties, ReportServiceImpl service, @Value("${common.timezone}") String timeZone) { return new ScheduledReportTaskSubmitter(taskScheduler, service, reportProperties.getSchedule(), timeZone); } @Bean - SlackPayloadExecutor slackPayloadExecutor(SlackClient client, ReportProperties reportProperties) { - return new SlackPayloadExecutor(client, reportProperties.getWebhooks()); + SlackReportExecutor slackPayloadExecutor(SlackClient client, SlackPayloadMapper mapper) { + return new SlackReportExecutor(client, mapper, reportProperties.getWebhooks().get(WebhookType.SLACK)); + } + + @Bean + WebhookSinkExecutor webhookSinkExecutor(FeignWebhookSink feignWebhookSink) { + return new WebhookSinkExecutor(feignWebhookSink, reportProperties.getWebhooks().get(WebhookType.PLAIN)); } @ConfigurationProperties(prefix = "report") @@ -38,6 +62,11 @@ SlackPayloadExecutor slackPayloadExecutor(SlackClient client, ReportProperties r @Setter static class ReportProperties { private Map schedule; - private Map webhooks; + private Map> webhooks; + } + + enum WebhookType { + SLACK, + PLAIN } } diff --git a/src/main/java/com/whiskels/notifier/reporting/service/GenericReportService.java b/src/main/java/com/whiskels/notifier/reporting/service/GenericReportService.java index 2bbc2702..829ebe89 100644 --- a/src/main/java/com/whiskels/notifier/reporting/service/GenericReportService.java +++ b/src/main/java/com/whiskels/notifier/reporting/service/GenericReportService.java @@ -1,6 +1,5 @@ package com.whiskels.notifier.reporting.service; -import com.slack.api.webhook.Payload; import com.whiskels.notifier.reporting.ReportType; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -12,7 +11,7 @@ public class GenericReportService { private final DataFetchService dataFetchService; private final ReportMessageConverter messageCreator; - public Iterable prepareReports() { + public Iterable prepareReports() { var data = dataFetchService.fetch(); return messageCreator.convert(data); } diff --git a/src/main/java/com/whiskels/notifier/reporting/service/Report.java b/src/main/java/com/whiskels/notifier/reporting/service/Report.java new file mode 100644 index 00000000..4997fe57 --- /dev/null +++ b/src/main/java/com/whiskels/notifier/reporting/service/Report.java @@ -0,0 +1,36 @@ +package com.whiskels.notifier.reporting.service; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +@Builder +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@EqualsAndHashCode +public class Report { + private final String header; + @Builder.Default + private final List body = new ArrayList<>(); + private final boolean notifyChannel; + private final String banner; + + public Report addBody(String text) { + body.add(ReportBodyBlock.builder().text(text).build()); + return this; + } + + public Report addBody(String text, String mediaContentUrl) { + body.add(ReportBodyBlock.builder().text(text).mediaContentUrl(mediaContentUrl).build()); + return this; + } + + @Builder + public record ReportBodyBlock(String text, String mediaContentUrl) { + } +} diff --git a/src/main/java/com/whiskels/notifier/reporting/service/ReportMessageConverter.java b/src/main/java/com/whiskels/notifier/reporting/service/ReportMessageConverter.java index 13167a49..c585208b 100644 --- a/src/main/java/com/whiskels/notifier/reporting/service/ReportMessageConverter.java +++ b/src/main/java/com/whiskels/notifier/reporting/service/ReportMessageConverter.java @@ -1,11 +1,9 @@ package com.whiskels.notifier.reporting.service; -import com.slack.api.webhook.Payload; - import javax.annotation.Nonnull; @FunctionalInterface public interface ReportMessageConverter { @Nonnull - Iterable convert(@Nonnull final ReportData data); + Iterable convert(@Nonnull final ReportData data); } diff --git a/src/main/java/com/whiskels/notifier/reporting/service/ReportServiceImpl.java b/src/main/java/com/whiskels/notifier/reporting/service/ReportServiceImpl.java index d11db6ce..74fe5212 100644 --- a/src/main/java/com/whiskels/notifier/reporting/service/ReportServiceImpl.java +++ b/src/main/java/com/whiskels/notifier/reporting/service/ReportServiceImpl.java @@ -1,37 +1,34 @@ package com.whiskels.notifier.reporting.service; +import com.whiskels.notifier.infrastructure.report.ReportExecutor; import com.whiskels.notifier.reporting.ReportService; import com.whiskels.notifier.reporting.ReportType; -import com.whiskels.notifier.reporting.SlackPayloadExecutor; import com.whiskels.notifier.reporting.exception.ExceptionEvent; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationEventPublisher; - -import javax.annotation.Nonnull; import org.springframework.stereotype.Component; +import javax.annotation.Nonnull; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; -import static java.lang.StringTemplate.STR; - @Slf4j @Component public class ReportServiceImpl implements ReportService { private final Map> processors; private final ApplicationEventPublisher publisher; - private final SlackPayloadExecutor payloadExecutor; + private final List reportExecutors; public ReportServiceImpl(final Collection> processors, - final SlackPayloadExecutor payloadExecutor, + final List reportExecutors, final ApplicationEventPublisher publisher) { this.processors = processors.stream() .collect(Collectors.toMap(GenericReportService::getType, Function.identity())); this.publisher = publisher; - this.payloadExecutor = payloadExecutor; + this.reportExecutors = reportExecutors; } @Override @@ -45,7 +42,7 @@ public void executeReport(@Nonnull final ReportType type) { } for (var report : processor.prepareReports()) { - payloadExecutor.send(type, report); + reportExecutors.forEach(executor -> executor.send(type, report)); } log.info("[{}] ...Completed", type); diff --git a/src/main/java/com/whiskels/notifier/reporting/service/SimpleReport.java b/src/main/java/com/whiskels/notifier/reporting/service/SimpleReport.java deleted file mode 100644 index 12f13ff3..00000000 --- a/src/main/java/com/whiskels/notifier/reporting/service/SimpleReport.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.whiskels.notifier.reporting.service; - -import com.slack.api.webhook.Payload; -import com.whiskels.notifier.infrastructure.slack.builder.SlackPayloadBuilder; - -public record SimpleReport(String header, String body) { - public Payload toSlackPayload() { - return SlackPayloadBuilder.builder() - .header(header) - .notifyChannel() - .block(body) - .build(); - } -} diff --git a/src/main/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/CustomerBirthdayInfoReportMessageConverter.java b/src/main/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/CustomerBirthdayInfoReportMessageConverter.java index e2fbb7de..0aa216b5 100644 --- a/src/main/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/CustomerBirthdayInfoReportMessageConverter.java +++ b/src/main/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/CustomerBirthdayInfoReportMessageConverter.java @@ -1,10 +1,9 @@ package com.whiskels.notifier.reporting.service.customer.birthday.convert; -import com.slack.api.webhook.Payload; import com.whiskels.notifier.reporting.domain.HasBirthday; +import com.whiskels.notifier.reporting.service.Report; import com.whiskels.notifier.reporting.service.ReportData; import com.whiskels.notifier.reporting.service.ReportMessageConverter; -import com.whiskels.notifier.reporting.service.SimpleReport; import com.whiskels.notifier.reporting.service.customer.birthday.domain.CustomerBirthdayInfo; import lombok.AllArgsConstructor; import lombok.Builder; @@ -22,19 +21,19 @@ @Slf4j @AllArgsConstructor public class CustomerBirthdayInfoReportMessageConverter implements ReportMessageConverter { - private final List contexts; + private final List contexts; private final String noData; @Nonnull @Override - public Iterable convert(@Nonnull ReportData data) { + public Iterable convert(@Nonnull ReportData data) { return contexts.stream() .map(context -> createReport(data, context)) .filter(Objects::nonNull) .toList(); } - private Payload createReport(ReportData data, ReportContext context) { + private Report createReport(ReportData data, com.whiskels.notifier.reporting.service.customer.birthday.convert.ReportContext context) { log.debug("Creating customer birthday event payload"); List birthdays = data.data().stream() .filter(dto -> context.getPredicate().test(dto, data.requestDate())) @@ -47,7 +46,10 @@ private Payload createReport(ReportData data, ReportContex return null; } var message = birthdays.isEmpty() ? noData : collectToBulletListString(birthdays, CustomerBirthdayInfoDto::toReportString); - return new SimpleReport(context.getHeaderMapper().apply(data.requestDate()), message).toSlackPayload(); + return Report.builder() + .header(context.getHeaderMapper().apply(data.requestDate())) + .build() + .addBody(message); } @Builder diff --git a/src/main/java/com/whiskels/notifier/reporting/service/customer/debt/convert/CustomerDebtReportMessageConverter.java b/src/main/java/com/whiskels/notifier/reporting/service/customer/debt/convert/CustomerDebtReportMessageConverter.java index beba5415..cd9e3136 100644 --- a/src/main/java/com/whiskels/notifier/reporting/service/customer/debt/convert/CustomerDebtReportMessageConverter.java +++ b/src/main/java/com/whiskels/notifier/reporting/service/customer/debt/convert/CustomerDebtReportMessageConverter.java @@ -1,9 +1,8 @@ package com.whiskels.notifier.reporting.service.customer.debt.convert; -import com.slack.api.webhook.Payload; +import com.whiskels.notifier.reporting.service.Report; import com.whiskels.notifier.reporting.service.ReportData; import com.whiskels.notifier.reporting.service.ReportMessageConverter; -import com.whiskels.notifier.reporting.service.SimpleReport; import com.whiskels.notifier.reporting.service.customer.debt.domain.CustomerDebt; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -29,30 +28,31 @@ public class CustomerDebtReportMessageConverter implements ReportMessageConverte @Override @Nonnull - public Iterable convert(@Nonnull ReportData data) { + public Iterable convert(@Nonnull ReportData data) { return data.data().size() < SINGLE_REPORT_CUTOFF ? singleReport(data) : multiReport(data); } - private List singleReport(ReportData reportData) { - return singletonList(new SimpleReport( - STR."\{header}\{reportDate(reportData.requestDate())}", - mapToReportText(reportData.data()) - ).toSlackPayload() + private List singleReport(ReportData reportData) { + return singletonList( + Report.builder() + .header(STR."\{header}\{reportDate(reportData.requestDate())}") + .build() + .addBody(mapToReportText(reportData.data())) ); } - private List multiReport(ReportData reportData) { - List reports = new ArrayList<>(); + private List multiReport(ReportData reportData) { + List reports = new ArrayList<>(); var content = reportData.data(); int reportNum = 1; for (int i = 0; i < content.size(); i += SINGLE_REPORT_CUTOFF) { var subList = content.subList(i, Math.min(content.size(), i + SINGLE_REPORT_CUTOFF)); - reports.add(new SimpleReport( - STR."\{header}\{reportDate(reportData.requestDate())} #\{reportNum++}", - mapToReportText(subList)).toSlackPayload() - ); + reports.add(Report.builder() + .header(STR."\{header}\{reportDate(reportData.requestDate())} #\{reportNum++}") + .build() + .addBody(mapToReportText(subList))); } return reports; } diff --git a/src/main/java/com/whiskels/notifier/reporting/service/customer/payment/messaging/PaymentReportMessageConverter.java b/src/main/java/com/whiskels/notifier/reporting/service/customer/payment/messaging/PaymentReportMessageConverter.java index 099db1e8..14c79714 100644 --- a/src/main/java/com/whiskels/notifier/reporting/service/customer/payment/messaging/PaymentReportMessageConverter.java +++ b/src/main/java/com/whiskels/notifier/reporting/service/customer/payment/messaging/PaymentReportMessageConverter.java @@ -1,7 +1,6 @@ package com.whiskels.notifier.reporting.service.customer.payment.messaging; -import com.slack.api.webhook.Payload; -import com.whiskels.notifier.infrastructure.slack.builder.SlackPayloadBuilder; +import com.whiskels.notifier.reporting.service.Report; import com.whiskels.notifier.reporting.service.ReportData; import com.whiskels.notifier.reporting.service.ReportMessageConverter; import com.whiskels.notifier.reporting.service.customer.payment.domain.CustomerPaymentDto; @@ -33,14 +32,14 @@ public class PaymentReportMessageConverter implements ReportMessageConverter convert(@Nonnull ReportData reportData) { + public Iterable convert(@Nonnull ReportData reportData) { var data = reportData.data(); - var payload = SlackPayloadBuilder.builder() + var report = Report.builder() .header(header + reportDate(reportData.requestDate())) - .notifyChannel() - .block(mapToReportText(data), reportPic(data)) - .build(); - return singleton(payload); + .notifyChannel(true) + .build() + .addBody(mapToReportText(data), reportPic(data)); + return singleton(report); } private String mapToReportText(List data) { diff --git a/src/main/java/com/whiskels/notifier/reporting/service/employee/convert/EmployeeEventReportMessageConverter.java b/src/main/java/com/whiskels/notifier/reporting/service/employee/convert/EmployeeEventReportMessageConverter.java index a84c9fc5..55748e7b 100644 --- a/src/main/java/com/whiskels/notifier/reporting/service/employee/convert/EmployeeEventReportMessageConverter.java +++ b/src/main/java/com/whiskels/notifier/reporting/service/employee/convert/EmployeeEventReportMessageConverter.java @@ -1,7 +1,6 @@ package com.whiskels.notifier.reporting.service.employee.convert; -import com.slack.api.webhook.Payload; -import com.whiskels.notifier.infrastructure.slack.builder.SlackPayloadBuilder; +import com.whiskels.notifier.reporting.service.Report; import com.whiskels.notifier.reporting.service.ReportData; import com.whiskels.notifier.reporting.service.ReportMessageConverter; import com.whiskels.notifier.reporting.service.employee.domain.Employee; @@ -16,7 +15,6 @@ import java.util.function.Function; import java.util.stream.Collectors; -import static com.whiskels.notifier.infrastructure.slack.builder.SlackPayloadBuilder.builder; import static com.whiskels.notifier.utilities.collections.StreamUtil.collectToBulletListString; @Slf4j @@ -35,14 +33,14 @@ public class EmployeeEventReportMessageConverter implements ReportMessageConvert @Nonnull @Override - public Iterable convert(@Nonnull ReportData data) { + public Iterable convert(@Nonnull ReportData data) { return contexts.stream() .map(context -> createReport(data, context)) .filter(Objects::nonNull) .toList(); } - private Payload createReport(ReportData data, ReportContext context) { + private Report createReport(ReportData data, ReportContext context) { var skipEmpty = context.getSkipEmpty().test(data.requestDate()); List birthdays = data.data().stream() @@ -62,25 +60,26 @@ private Payload createReport(ReportData data, ReportContext context) { return null; } - SlackPayloadBuilder builder = builder() + var report = Report.builder() .header(context.getHeaderMapper().apply(data.requestDate())) - .notifyChannel(); + .notifyChannel(true) + .build(); if (!birthdays.isEmpty() || !skipEmpty) { log.debug("Added birthday block to payload: empty = {}, skipEmpty = {}", birthdays.isEmpty(), skipEmpty); - addBlock(builder, birthdaySubheader, birthdays, EmployeeDto::toBirthdayString); + addBlock(report, birthdaySubheader, birthdays, EmployeeDto::toBirthdayString); } if (!anniversaries.isEmpty() || !skipEmpty) { log.debug("Added anniversary block to payload: empty = {}, skipEmpty = {}", anniversaries.isEmpty(), skipEmpty); - addBlock(builder, anniversarySubheader, anniversaries, e -> e.toWorkAnniversaryString(clock)); + addBlock(report, anniversarySubheader, anniversaries, e -> e.toWorkAnniversaryString(clock)); } - return builder.build(); + return report; } - private void addBlock(SlackPayloadBuilder builder, String header, List data, Function mappingFunction) { - builder.block(header) - .block(data.isEmpty() ? noData : collectToBulletListString(data, mappingFunction)); + private void addBlock(Report report, String header, List data, Function mappingFunction) { + report.addBody(header) + .addBody(data.isEmpty() ? noData : collectToBulletListString(data, mappingFunction)); } } diff --git a/src/main/java/com/whiskels/notifier/utilities/collections/StreamUtil.java b/src/main/java/com/whiskels/notifier/utilities/collections/StreamUtil.java index c697ca0e..d8058f64 100644 --- a/src/main/java/com/whiskels/notifier/utilities/collections/StreamUtil.java +++ b/src/main/java/com/whiskels/notifier/utilities/collections/StreamUtil.java @@ -18,7 +18,7 @@ public final class StreamUtil { @SafeVarargs public static > List filterAndSort(List list, Predicate... predicates) { return list.stream() - .filter(Stream.of(predicates).reduce(x -> true, Predicate::and)) + .filter(Stream.of(predicates).reduce(_ -> true, Predicate::and)) .sorted() .collect(toList()); } @@ -26,13 +26,13 @@ public static > List filterAndSort(List list, Pred @SafeVarargs public static List filterAndSort(List list, Comparator comparator, Predicate... predicates) { return list.stream() - .filter(Stream.of(predicates).reduce(x -> true, Predicate::and)) + .filter(Stream.of(predicates).reduce(_ -> true, Predicate::and)) .sorted(comparator) .collect(toList()); } - public static List map(List list, Function func) { - return list.stream().map(func).collect(toList()); + public static List map(Collection coll, Function func) { + return coll.stream().map(func).collect(toList()); } public static String collectToBulletListString(Collection collection, Function toStringFunc) { diff --git a/src/main/resources/application-mock.yaml b/src/main/resources/application-mock.yaml index 5de5987b..3340650e 100644 --- a/src/main/resources/application-mock.yaml +++ b/src/main/resources/application-mock.yaml @@ -1,18 +1,12 @@ -spring: - datasource: - url: ${DATABASE_URL} - jpa: - show-sql: true - username: ${MOCK_DATABASE_USER} - password: ${MOCK_DATABASE_PASSWORD} report: -# schedule: -# CUSTOMER_BIRTHDAY: 0 * * * * * -# CUSTOMER_DEBT: 0 * * * * * -# CUSTOMER_PAYMENT: 0 * * * * * -# EMPLOYEE_EVENT: 0 * * * * * + schedule: + CUSTOMER_BIRTHDAY: 0 * * * * * + CUSTOMER_DEBT: 0 * * * * * + CUSTOMER_PAYMENT: 0 * * * * * + EMPLOYEE_EVENT: 0 * * * * * webhooks: - CUSTOMER_BIRTHDAY: ${SLACK_WEBHOOK} - CUSTOMER_DEBT: ${SLACK_WEBHOOK} - CUSTOMER_PAYMENT: ${SLACK_WEBHOOK} - EMPLOYEE_EVENT: ${SLACK_WEBHOOK} + PLAIN: + CUSTOMER_BIRTHDAY: ${WEBHOOK_URL} + CUSTOMER_DEBT: ${WEBHOOK_URL} + CUSTOMER_PAYMENT: ${WEBHOOK_URL} + EMPLOYEE_EVENT: ${WEBHOOK_URL} diff --git a/src/main/resources/application-prod.yaml b/src/main/resources/application-prod.yaml index 8749c67c..4cf14055 100644 --- a/src/main/resources/application-prod.yaml +++ b/src/main/resources/application-prod.yaml @@ -17,10 +17,15 @@ report: CUSTOMER_PAYMENT: 0 1 13 * * MON-FRI EMPLOYEE_EVENT: 0 0 9 * * * webhooks: - CUSTOMER_BIRTHDAY: ${CUSTOMER_BIRTHDAY_SLACK_WEBHOOK} - CUSTOMER_DEBT: ${CUSTOMER_DEBT_SLACK_WEBHOOK} - CUSTOMER_PAYMENT: ${CUSTOMER_PAYMENT_SLACK_WEBHOOK} - EMPLOYEE_EVENT: ${EMPLOYEE_SLACK_WEBHOOK} + SLACK: + CUSTOMER_BIRTHDAY: ${CUSTOMER_BIRTHDAY_SLACK_WEBHOOK} + CUSTOMER_DEBT: ${CUSTOMER_DEBT_SLACK_WEBHOOK} + CUSTOMER_PAYMENT: ${CUSTOMER_PAYMENT_SLACK_WEBHOOK} + EMPLOYEE_EVENT: ${EMPLOYEE_SLACK_WEBHOOK} + PLAIN: + CUSTOMER_BIRTHDAY: ${CUSTOMER_BIRTHDAY_WEBHOOK} + CUSTOMER_PAYMENT: ${CUSTOMER_PAYMENT_WEBHOOK} + EMPLOYEE_EVENT: ${EMPLOYEE_WEBHOOK} google: spreadsheets: parameters: diff --git a/src/test/java/com/whiskels/notifier/infrastructure/slack/SlackClientTest.java b/src/test/java/com/whiskels/notifier/infrastructure/slack/SlackClientTest.java index deb9905f..dd9a7315 100644 --- a/src/test/java/com/whiskels/notifier/infrastructure/slack/SlackClientTest.java +++ b/src/test/java/com/whiskels/notifier/infrastructure/slack/SlackClientTest.java @@ -3,6 +3,7 @@ import com.slack.api.Slack; import com.slack.api.webhook.Payload; import com.slack.api.webhook.WebhookResponse; +import com.whiskels.notifier.infrastructure.report.slack.SlackClient; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; diff --git a/src/test/java/com/whiskels/notifier/infrastructure/slack/builder/SlackPayloadBuilderTest.java b/src/test/java/com/whiskels/notifier/infrastructure/slack/builder/SlackPayloadBuilderTest.java index e79c7c1b..a3137166 100644 --- a/src/test/java/com/whiskels/notifier/infrastructure/slack/builder/SlackPayloadBuilderTest.java +++ b/src/test/java/com/whiskels/notifier/infrastructure/slack/builder/SlackPayloadBuilderTest.java @@ -1,6 +1,7 @@ package com.whiskels.notifier.infrastructure.slack.builder; import com.slack.api.webhook.Payload; +import com.whiskels.notifier.infrastructure.report.slack.builder.SlackPayloadBuilder; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/whiskels/notifier/reporting/GenericReportServiceTest.java b/src/test/java/com/whiskels/notifier/reporting/GenericReportServiceTest.java index a3acccef..d7efc20e 100644 --- a/src/test/java/com/whiskels/notifier/reporting/GenericReportServiceTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/GenericReportServiceTest.java @@ -1,8 +1,8 @@ package com.whiskels.notifier.reporting; -import com.slack.api.webhook.Payload; import com.whiskels.notifier.reporting.service.DataFetchService; import com.whiskels.notifier.reporting.service.GenericReportService; +import com.whiskels.notifier.reporting.service.Report; import com.whiskels.notifier.reporting.service.ReportData; import com.whiskels.notifier.reporting.service.ReportMessageConverter; import org.junit.jupiter.api.DisplayName; @@ -34,12 +34,12 @@ class GenericReportServiceTest { @Test @DisplayName("Should prepare reports") void shouldPrepareReports() { - var payload = Payload.builder().build(); + var payload = Report.builder().build(); when(dataFetchService.fetch()).thenReturn(new ReportData<>(List.of("Data1", "Data2"), LocalDate.now())); when(messageCreator.convert(any())).thenReturn(List.of(payload)); - Iterable payloads = genericReportService.prepareReports(); - List payloadList = (List) payloads; + Iterable payloads = genericReportService.prepareReports(); + List payloadList = (List) payloads; assertEquals(1, payloadList.size()); assertEquals(payloadList.getFirst(), payload); diff --git a/src/test/java/com/whiskels/notifier/reporting/ReportPropertiesTest.java b/src/test/java/com/whiskels/notifier/reporting/ReportPropertiesTest.java index 02632ff3..9162b461 100644 --- a/src/test/java/com/whiskels/notifier/reporting/ReportPropertiesTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/ReportPropertiesTest.java @@ -16,7 +16,7 @@ @SpringBootTest(classes = ReportPropertiesTest.TestConfig.class) @TestPropertySource(properties = { "report.schedule.EMPLOYEE_EVENT=0 0 12 * * MON-FRI", - "report.webhooks.EMPLOYEE_EVENT=https://webhook.example.com/report1" + "report.webhooks.SLACK.EMPLOYEE_EVENT=https://webhook.example.com/report1" }) public class ReportPropertiesTest { @@ -27,10 +27,10 @@ public class ReportPropertiesTest { @DisplayName("Should bind properties") void shouldBingProperties() { Map schedule = reportProperties.getSchedule(); - Map webhooks = reportProperties.getWebhooks(); + Map<_ReportConfig.WebhookType, Map> webhooks = reportProperties.getWebhooks(); assertEquals("0 0 12 * * MON-FRI", schedule.get(EMPLOYEE_EVENT)); - assertEquals("https://webhook.example.com/report1", webhooks.get(EMPLOYEE_EVENT)); + assertEquals("https://webhook.example.com/report1", webhooks.get(_ReportConfig.WebhookType.SLACK).get(EMPLOYEE_EVENT)); } @Configuration diff --git a/src/test/java/com/whiskels/notifier/reporting/ReportServiceTest.java b/src/test/java/com/whiskels/notifier/reporting/ReportServiceTest.java index df88565b..c9cf9819 100644 --- a/src/test/java/com/whiskels/notifier/reporting/ReportServiceTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/ReportServiceTest.java @@ -1,8 +1,9 @@ package com.whiskels.notifier.reporting; -import com.slack.api.webhook.Payload; +import com.whiskels.notifier.infrastructure.report.slack.SlackReportExecutor; import com.whiskels.notifier.reporting.exception.ExceptionEvent; import com.whiskels.notifier.reporting.service.GenericReportService; +import com.whiskels.notifier.reporting.service.Report; import com.whiskels.notifier.reporting.service.ReportServiceImpl; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -12,7 +13,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.context.ApplicationEventPublisher; -import java.io.IOException; import java.util.List; import static com.whiskels.notifier.reporting.ReportType.CUSTOMER_BIRTHDAY; @@ -27,7 +27,7 @@ @ExtendWith(MockitoExtension.class) class ReportServiceTest { - private static final Payload MOCKED_REPORT = Payload.builder().build(); + private static final Report MOCKED_REPORT = Report.builder().build(); @Mock private GenericReportService genericReportServiceOne; @@ -36,7 +36,7 @@ class ReportServiceTest { private GenericReportService genericReportServiceTwo; @Mock - private SlackPayloadExecutor payloadExecutor; + private SlackReportExecutor payloadExecutor; @Mock private ApplicationEventPublisher publisher; @@ -49,12 +49,12 @@ void initReportService() { lenient().when(genericReportServiceOne.prepareReports()).thenReturn(List.of(MOCKED_REPORT)); lenient().when(genericReportServiceTwo.getType()).thenReturn(CUSTOMER_DEBT); lenient().when(genericReportServiceTwo.prepareReports()).thenThrow(new RuntimeException("Test exception")); - reportService = new ReportServiceImpl(List.of(genericReportServiceOne, genericReportServiceTwo), payloadExecutor, publisher); + reportService = new ReportServiceImpl(List.of(genericReportServiceOne, genericReportServiceTwo), List.of(payloadExecutor), publisher); } @Test @DisplayName("Should execute report successfully") - void shouldExecuteReportSuccessfully() throws IOException { + void shouldExecuteReportSuccessfully() { ReportType type = EMPLOYEE_EVENT; reportService.executeReport(type); diff --git a/src/test/java/com/whiskels/notifier/reporting/ReportTest.java b/src/test/java/com/whiskels/notifier/reporting/ReportTest.java new file mode 100644 index 00000000..db94d702 --- /dev/null +++ b/src/test/java/com/whiskels/notifier/reporting/ReportTest.java @@ -0,0 +1,36 @@ +package com.whiskels.notifier.reporting; + +import com.whiskels.notifier.reporting.service.Report; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ReportTest { + + @Test + @DisplayName("Should construct SimpleReport via constructor") + void shouldConstructReport() { + var header = "Test Header"; + var banner = "Test Banner"; + var body = "Test Body"; + Report report = Report.builder() + .header(header) + .notifyChannel(true) + .banner(banner) + .build() + .addBody(body); + + assertEquals(header, report.getHeader()); + assertEquals(banner, report.getBanner()); + assertTrue(report.isNotifyChannel()); + assertThat(report.getBody()).hasSize(1) + .allSatisfy(bodyBlock -> { + assertEquals(body, bodyBlock.text()); + assertNull(bodyBlock.mediaContentUrl()); + }); + } +} diff --git a/src/test/java/com/whiskels/notifier/reporting/SimpleReportTest.java b/src/test/java/com/whiskels/notifier/reporting/SimpleReportTest.java deleted file mode 100644 index eca0fe03..00000000 --- a/src/test/java/com/whiskels/notifier/reporting/SimpleReportTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.whiskels.notifier.reporting; - -import com.slack.api.model.block.HeaderBlock; -import com.slack.api.model.block.SectionBlock; -import com.slack.api.webhook.Payload; -import com.whiskels.notifier.reporting.service.SimpleReport; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -class SimpleReportTest { - - @Test - @DisplayName("Should construct SimpleReport via constructor") - void shouldConstructSimpleReport() { - SimpleReport report = new SimpleReport("Test Header", "Test Body"); - - assertEquals("Test Header", report.header()); - assertEquals("Test Body", report.body()); - } - - @Test - @DisplayName("Should convert Simple Report to Slack Payload") - void shouldConvertToSlackPayload() { - SimpleReport report = new SimpleReport("Test Header", "Test Body"); - Payload payload = report.toSlackPayload(); - - assertNotNull(payload); - assertEquals(payload.getText(), "Test Header"); - assertEquals(((HeaderBlock) payload.getBlocks().get(0)).getText().getText(), "Test Header"); - assertEquals(((SectionBlock) payload.getBlocks().get(1)).getText().getText(), "@channel"); - assertEquals(((SectionBlock) payload.getBlocks().get(2)).getText().getText(), "Test Body"); - } -} diff --git a/src/test/java/com/whiskels/notifier/reporting/executor/SlackPayloadExecutorTest.java b/src/test/java/com/whiskels/notifier/reporting/executor/SlackReportExecutorTest.java similarity index 51% rename from src/test/java/com/whiskels/notifier/reporting/executor/SlackPayloadExecutorTest.java rename to src/test/java/com/whiskels/notifier/reporting/executor/SlackReportExecutorTest.java index d4b1bb14..b87d5618 100644 --- a/src/test/java/com/whiskels/notifier/reporting/executor/SlackPayloadExecutorTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/executor/SlackReportExecutorTest.java @@ -1,9 +1,11 @@ package com.whiskels.notifier.reporting.executor; import com.slack.api.webhook.Payload; -import com.whiskels.notifier.infrastructure.slack.SlackClient; +import com.whiskels.notifier.infrastructure.report.slack.SlackClient; +import com.whiskels.notifier.infrastructure.report.slack.SlackPayloadMapper; +import com.whiskels.notifier.infrastructure.report.slack.SlackReportExecutor; import com.whiskels.notifier.reporting.ReportType; -import com.whiskels.notifier.reporting.SlackPayloadExecutor; +import com.whiskels.notifier.reporting.service.Report; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -16,39 +18,43 @@ import static com.whiskels.notifier.reporting.ReportType.CUSTOMER_BIRTHDAY; import static com.whiskels.notifier.reporting.ReportType.EMPLOYEE_EVENT; import static java.util.Collections.emptyMap; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @ExtendWith(MockitoExtension.class) -class SlackPayloadExecutorTest { +class SlackReportExecutorTest { private static final Payload DUMMY_PAYLOAD = Payload.builder().build(); @Mock - private SlackClient slackClient; + private SlackClient client; + @Mock + private SlackPayloadMapper mapper; - private SlackPayloadExecutor slackPayloadExecutor; + private SlackReportExecutor executor; @Test @DisplayName("Should send when type exists") void shouldSentWhenTypeExists() throws IOException { Map webhookMappings = Map.of(EMPLOYEE_EVENT, "https://example.com/some-webhook"); - slackPayloadExecutor = new SlackPayloadExecutor(slackClient, webhookMappings); + executor = new SlackReportExecutor(client, mapper, webhookMappings); + given(mapper.map(any())).willReturn(DUMMY_PAYLOAD); - slackPayloadExecutor.send(EMPLOYEE_EVENT, DUMMY_PAYLOAD); + executor.send(EMPLOYEE_EVENT, Report.builder().build()); - verify(slackClient).send(webhookMappings.get(EMPLOYEE_EVENT), DUMMY_PAYLOAD); + verify(client).send(webhookMappings.get(EMPLOYEE_EVENT), DUMMY_PAYLOAD); } @Test @DisplayName("Should throw exception when type does not exist") - void shouldThrowExceptionWhenTypeDoesNotExist() throws IOException { - slackPayloadExecutor = new SlackPayloadExecutor(slackClient, emptyMap()); + void shouldTNothrowExceptionWhenTypeDoesNotExist() throws IOException { + executor = new SlackReportExecutor(client, mapper, emptyMap()); - assertThrows(IllegalStateException.class, () -> slackPayloadExecutor.send(CUSTOMER_BIRTHDAY, DUMMY_PAYLOAD)); + assertDoesNotThrow(() -> executor.send(CUSTOMER_BIRTHDAY, Report.builder().build())); - verify(slackClient, never()).send(anyString(), any(Payload.class)); + verify(client, never()).send(anyString(), any(Payload.class)); } } \ No newline at end of file diff --git a/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/CustomerBirthdayInfoReportMessageConverterTest.java b/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/CustomerBirthdayInfoReportMessageConverterTest.java index 71e6a878..54aebc7d 100644 --- a/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/CustomerBirthdayInfoReportMessageConverterTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/CustomerBirthdayInfoReportMessageConverterTest.java @@ -1,17 +1,14 @@ package com.whiskels.notifier.reporting.service.customer.birthday.convert; -import com.slack.api.webhook.Payload; +import com.whiskels.notifier.reporting.service.Report; import com.whiskels.notifier.reporting.service.ReportData; import com.whiskels.notifier.reporting.service.customer.birthday.domain.CustomerBirthdayInfo; -import com.whiskels.notifier.utilities.collections.StreamUtil; -import lombok.SneakyThrows; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import java.time.LocalDate; import java.util.List; -import static com.whiskels.notifier.JsonUtils.MAPPER; import static com.whiskels.notifier.MockedClockConfiguration.CLOCK; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; @@ -23,105 +20,30 @@ class CustomerBirthdayInfoReportMessageConverterTest { private static final String noData = "No Data"; - private static final String birthdaySubheader = "Happy Birthday!"; private CustomerBirthdayInfoReportMessageConverter converter; @Test @DisplayName("Should convert customer payload") void shouldConvertCustomerPayload() { - var expectedOne = """ - { - "threadTs" : null, - "text" : "Birthday Header", - "channel" : null, - "username" : null, - "iconUrl" : null, - "iconEmoji" : null, - "blocks" : [ { - "type" : "header", - "blockId" : "0", - "text" : { - "type" : "plain_text", - "text" : "Birthday Header", - "emoji" : false - } - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "@channel", - "verbatim" : null - }, - "blockId" : "1", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "• John Doe 01.01 (Test company)", - "verbatim" : null - }, - "blockId" : "2", - "fields" : null, - "accessory" : null - } ], - "attachments" : null, - "unfurlLinks" : null, - "unfurlMedia" : null, - "metadata" : null - }"""; - var expectedTwo = """ - { - "threadTs" : null, - "text" : "Another Birthday Header", - "channel" : null, - "username" : null, - "iconUrl" : null, - "iconEmoji" : null, - "blocks" : [ { - "type" : "header", - "blockId" : "0", - "text" : { - "type" : "plain_text", - "text" : "Another Birthday Header", - "emoji" : false - } - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "@channel", - "verbatim" : null - }, - "blockId" : "1", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "No Data", - "verbatim" : null - }, - "blockId" : "2", - "fields" : null, - "accessory" : null - } ], - "attachments" : null, - "unfurlLinks" : null, - "unfurlMedia" : null, - "metadata" : null - }"""; + var birthdayHeader = "Birthday Header"; + var expectedOne = Report.builder() + .header(birthdayHeader) + .notifyChannel(false) + .build().addBody("• John Doe 01.01 (Test company)"); + var birthdayHeaderTwo = "Another Birthday Header"; + var expectedTwo = Report.builder() + .header(birthdayHeaderTwo) + .notifyChannel(false) + .build().addBody("No Data"); ReportContext contextOne = mock(ReportContext.class); when(contextOne.getSkipEmptyPredicate()).thenReturn(_ -> true); when(contextOne.getPredicate()).thenReturn((_, _) -> true); - when(contextOne.getHeaderMapper()).thenReturn(_ -> "Birthday Header"); + when(contextOne.getHeaderMapper()).thenReturn(_ -> birthdayHeader); ReportContext contextTwo = mock(ReportContext.class); when(contextTwo.getSkipEmptyPredicate()).thenReturn(_ -> false); when(contextTwo.getPredicate()).thenReturn((_, _) -> false); - when(contextTwo.getHeaderMapper()).thenReturn(_ -> "Another Birthday Header"); + when(contextTwo.getHeaderMapper()).thenReturn(_ -> birthdayHeaderTwo); var contexts = List.of(contextOne, contextTwo); @@ -131,13 +53,11 @@ void shouldConvertCustomerPayload() { customer(LocalDate.of(2000, 1, 1)) ), LocalDate.now(CLOCK)); - Iterable payloads = converter.convert(reportData); - List payloadList = (List) payloads; + List reports = (List) converter.convert(reportData); - assertFalse(payloadList.isEmpty()); - assertEquals(2, payloadList.size()); - assertThat(StreamUtil.map(payloadList, this::map)) - .containsExactly(expectedOne, expectedTwo); + assertFalse(reports.isEmpty()); + assertEquals(2, reports.size()); + assertThat(reports).containsExactly(expectedOne, expectedTwo); } @Test @@ -156,11 +76,6 @@ void shouldReturnNullIfSkipEmptyAndNoData() { assertFalse(actual.iterator().hasNext()); } - @SneakyThrows - private String map(Payload payload) { - return MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(payload); - } - private CustomerBirthdayInfo customer(LocalDate birthday) { return CustomerBirthdayInfo.builder() .name("John") diff --git a/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/BeforeEventReportContextTest.java b/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/BeforeEventReportDataTest.java similarity index 87% rename from src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/BeforeEventReportContextTest.java rename to src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/BeforeEventReportDataTest.java index 6a366b35..43312679 100644 --- a/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/BeforeEventReportContextTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/BeforeEventReportDataTest.java @@ -6,9 +6,11 @@ import java.time.LocalDate; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -class BeforeEventReportContextTest { +class BeforeEventReportDataTest { @Test @DisplayName("Should initialize header") diff --git a/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/DailyReportContextTest.java b/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/DailyReportDataTest.java similarity index 87% rename from src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/DailyReportContextTest.java rename to src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/DailyReportDataTest.java index d839d9b6..ad13eabf 100644 --- a/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/DailyReportContextTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/DailyReportDataTest.java @@ -6,9 +6,11 @@ import java.time.LocalDate; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -class DailyReportContextTest { +class DailyReportDataTest { @Test @DisplayName("Should initialize header") diff --git a/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/MonthMiddleReportContextTest.java b/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/MonthMiddleReportDataTest.java similarity index 90% rename from src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/MonthMiddleReportContextTest.java rename to src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/MonthMiddleReportDataTest.java index e2c7158d..3a236f48 100644 --- a/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/MonthMiddleReportContextTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/MonthMiddleReportDataTest.java @@ -6,9 +6,11 @@ import java.time.LocalDate; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -class MonthMiddleReportContextTest { +class MonthMiddleReportDataTest { @Test @DisplayName("Should initialize header") diff --git a/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/MonthStartReportContextTest.java b/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/MonthStartReportDataTest.java similarity index 91% rename from src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/MonthStartReportContextTest.java rename to src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/MonthStartReportDataTest.java index c0c7f546..380ff30f 100644 --- a/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/MonthStartReportContextTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/service/customer/birthday/convert/context/MonthStartReportDataTest.java @@ -6,9 +6,11 @@ import java.time.LocalDate; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -class MonthStartReportContextTest { +class MonthStartReportDataTest { @Test @DisplayName("Should initialize header") diff --git a/src/test/java/com/whiskels/notifier/reporting/service/customer/debt/convert/CustomerDebtReportMessageConverterTest.java b/src/test/java/com/whiskels/notifier/reporting/service/customer/debt/convert/CustomerDebtReportMessageConverterTest.java index dc9d3fea..8e782903 100644 --- a/src/test/java/com/whiskels/notifier/reporting/service/customer/debt/convert/CustomerDebtReportMessageConverterTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/service/customer/debt/convert/CustomerDebtReportMessageConverterTest.java @@ -1,6 +1,6 @@ package com.whiskels.notifier.reporting.service.customer.debt.convert; -import com.slack.api.webhook.Payload; +import com.whiskels.notifier.reporting.service.Report; import com.whiskels.notifier.reporting.service.ReportData; import com.whiskels.notifier.reporting.service.customer.debt.domain.CurrencyRate; import com.whiskels.notifier.reporting.service.customer.debt.domain.CustomerDebt; @@ -12,7 +12,6 @@ import java.util.List; import java.util.Map; -import static com.whiskels.notifier.JsonUtils.MAPPER; import static com.whiskels.notifier.MockedClockConfiguration.EXPECTED_DATE; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; @@ -27,218 +26,104 @@ class CustomerDebtReportMessageConverterTest { @Test @DisplayName("Should convert to single report") - void shouldConvertToSingleReport() throws Exception { + void shouldConvertToSingleReport() { // Given - String expected = """ - { - "threadTs" : null, - "text" : "Debt Report on 23-02-2024", - "channel" : null, - "username" : null, - "iconUrl" : null, - "iconEmoji" : null, - "blocks" : [ { - "type" : "header", - "blockId" : "0", - "text" : { - "type" : "plain_text", - "text" : "Debt Report on 23-02-2024", - "emoji" : false - } - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "@channel", - "verbatim" : null - }, - "blockId" : "1", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment", - "verbatim" : null - }, - "blockId" : "2", - "fields" : null, - "accessory" : null - } ], - "attachments" : null, - "unfurlLinks" : null, - "unfurlMedia" : null, - "metadata" : null - }"""; + var expected = Report.builder() + .header("Debt Report on 23-02-2024") + .build() + .addBody("*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment"); CustomerDebt customerDebt = createCustomerDebt(); ReportData reportData = new ReportData<>(singletonList(customerDebt), EXPECTED_DATE); // When - var result = (List) converter.convert(reportData); + var result = (List) converter.convert(reportData); // Then assertNotNull(result); assertEquals(1, result.size()); - assertEquals(expected, MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(result.getFirst())); + assertEquals(expected, result.getFirst()); } @Test @DisplayName("Should convert to multiple report") - void shouldConvertToMultipleReports() throws Exception{ + void shouldConvertToMultipleReports() { // Given - String expectedOne = """ - { - "threadTs" : null, - "text" : "Debt Report on 23-02-2024 #1", - "channel" : null, - "username" : null, - "iconUrl" : null, - "iconEmoji" : null, - "blocks" : [ { - "type" : "header", - "blockId" : "0", - "text" : { - "type" : "plain_text", - "text" : "Debt Report on 23-02-2024 #1", - "emoji" : false - } - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "@channel", - "verbatim" : null - }, - "blockId" : "1", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment", - "verbatim" : null - }, - "blockId" : "2", - "fields" : null, - "accessory" : null - } ], - "attachments" : null, - "unfurlLinks" : null, - "unfurlMedia" : null, - "metadata" : null - }"""; - String expectedTwo = """ - { - "threadTs" : null, - "text" : "Debt Report on 23-02-2024 #2", - "channel" : null, - "username" : null, - "iconUrl" : null, - "iconEmoji" : null, - "blocks" : [ { - "type" : "header", - "blockId" : "0", - "text" : { - "type" : "plain_text", - "text" : "Debt Report on 23-02-2024 #2", - "emoji" : false - } - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "@channel", - "verbatim" : null - }, - "blockId" : "1", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment\\n\\n*Test Contractor*\\n Test Finance Subject\\n Test Payment Method\\n Test Manager\\n *1 500 USD*\\nTest Comment", - "verbatim" : null - }, - "blockId" : "2", - "fields" : null, - "accessory" : null - } ], - "attachments" : null, - "unfurlLinks" : null, - "unfurlMedia" : null, - "metadata" : null - }"""; + var expectedOne = Report.builder() + .header("Debt Report on 23-02-2024 #1") + .build() + .addBody("*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment\n\n*Test Contractor*\n Test Finance Subject\n Test Payment Method\n Test Manager\n *1 500 USD*\nTest Comment"); + + + var expectedTwo = Report.builder() + .header("Debt Report on 23-02-2024 #2") + .build() + .addBody(""" + *Test Contractor* + Test Finance Subject + Test Payment Method + Test Manager + *1 500 USD* + Test Comment + + *Test Contractor* + Test Finance Subject + Test Payment Method + Test Manager + *1 500 USD* + Test Comment + + *Test Contractor* + Test Finance Subject + Test Payment Method + Test Manager + *1 500 USD* + Test Comment + + *Test Contractor* + Test Finance Subject + Test Payment Method + Test Manager + *1 500 USD* + Test Comment + + *Test Contractor* + Test Finance Subject + Test Payment Method + Test Manager + *1 500 USD* + Test Comment"""); + List customerDebts = Collections.nCopies(25, createCustomerDebt()); ReportData reportData = new ReportData<>(customerDebts, EXPECTED_DATE); // When - var result = (List) converter.convert(reportData); + var result = (List) converter.convert(reportData); // Then assertNotNull(result); assertEquals(2, result.size()); - assertEquals(expectedOne, MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(result.getFirst())); - assertEquals(expectedTwo, MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(result.get(1))); + assertEquals(expectedOne, result.getFirst()); + assertEquals(expectedTwo, result.get(1)); } @Test @DisplayName("Should convert when data is empty") - void shouldConvertWhenDataIsEmpty() throws Exception { + void shouldConvertWhenDataIsEmpty() { // Given - String expected = """ - { - "threadTs" : null, - "text" : "Debt Report on 23-02-2024", - "channel" : null, - "username" : null, - "iconUrl" : null, - "iconEmoji" : null, - "blocks" : [ { - "type" : "header", - "blockId" : "0", - "text" : { - "type" : "plain_text", - "text" : "Debt Report on 23-02-2024", - "emoji" : false - } - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "@channel", - "verbatim" : null - }, - "blockId" : "1", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "No data available", - "verbatim" : null - }, - "blockId" : "2", - "fields" : null, - "accessory" : null - } ], - "attachments" : null, - "unfurlLinks" : null, - "unfurlMedia" : null, - "metadata" : null - }"""; + var expected = Report.builder() + .header("Debt Report on 23-02-2024") + .build() + .addBody("No data available"); + ReportData reportData = new ReportData<>(emptyList(), EXPECTED_DATE); // When - var result = (List) converter.convert(reportData); + var result = (List) converter.convert(reportData); // Then assertNotNull(result); assertEquals(1, result.size()); - assertEquals(expected, MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(result.getFirst())); + assertEquals(expected, result.getFirst()); } private CustomerDebt createCustomerDebt() { diff --git a/src/test/java/com/whiskels/notifier/reporting/service/customer/payment/messaging/PaymentReportMessageConverterTest.java b/src/test/java/com/whiskels/notifier/reporting/service/customer/payment/messaging/PaymentReportMessageConverterTest.java index 8c364733..71e0a891 100644 --- a/src/test/java/com/whiskels/notifier/reporting/service/customer/payment/messaging/PaymentReportMessageConverterTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/service/customer/payment/messaging/PaymentReportMessageConverterTest.java @@ -1,6 +1,6 @@ package com.whiskels.notifier.reporting.service.customer.payment.messaging; -import com.slack.api.webhook.Payload; +import com.whiskels.notifier.reporting.service.Report; import com.whiskels.notifier.reporting.service.ReportData; import com.whiskels.notifier.reporting.service.customer.payment.domain.CustomerPaymentDto; import org.junit.jupiter.api.DisplayName; @@ -11,10 +11,9 @@ import java.util.List; import java.util.Map; -import static com.whiskels.notifier.JsonUtils.MAPPER; -import static com.whiskels.notifier.TestUtil.assertEqualsIgnoringCR; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class PaymentReportMessageConverterTest { @@ -26,67 +25,25 @@ class PaymentReportMessageConverterTest { @Test @DisplayName("Should prepare empty report") - void shouldPrepareEmptyReport() throws Exception { + void shouldPrepareEmptyReport() { LocalDate regularDate = LocalDate.of(2023, 6, 10); ReportData data = new ReportData<>(emptyList(), regularDate); - Iterable iterable = converter.convert(data); + var iterable = converter.convert(data); var iterator = iterable.iterator(); assertTrue(iterator.hasNext()); - var payload = iterator.next(); - assertEqualsIgnoringCR( - """ - { - "threadTs" : null, - "text" : "Payment report on 10-06-2023", - "channel" : null, - "username" : null, - "iconUrl" : null, - "iconEmoji" : null, - "blocks" : [ { - "type" : "header", - "blockId" : "0", - "text" : { - "type" : "plain_text", - "text" : "Payment report on 10-06-2023", - "emoji" : false - } - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "@channel", - "verbatim" : null - }, - "blockId" : "1", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "Nothing", - "verbatim" : null - }, - "blockId" : "2", - "fields" : null, - "accessory" : { - "type" : "image", - "image_url" : "Test", - "alt_text" : "Funny pic" - } - } ], - "attachments" : null, - "unfurlLinks" : null, - "unfurlMedia" : null, - "metadata" : null - }""", MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(payload)); + var report = iterator.next(); + assertEquals(Report.builder() + .header("Payment report on 10-06-2023") + .notifyChannel(true) + .build() + .addBody("Nothing", "Test"), report); } @Test @DisplayName("Should prepare report") - void shouldPrepareReport() throws Exception { + void shouldPrepareReport() { LocalDate regularDate = LocalDate.of(2023, 6, 10); CustomerPaymentDto dtoOne = CustomerPaymentDto.builder() .amount(new BigDecimal("100000")) @@ -102,56 +59,16 @@ void shouldPrepareReport() throws Exception { .build(); ReportData data = new ReportData<>(List.of(dtoOne, dtoTwo), regularDate); - Iterable iterable = converter.convert(data); + var iterable = converter.convert(data); var iterator = iterable.iterator(); assertTrue(iterator.hasNext()); - var payload = iterator.next(); - assertEqualsIgnoringCR(""" - { - "threadTs" : null, - "text" : "Payment report on 10-06-2023", - "channel" : null, - "username" : null, - "iconUrl" : null, - "iconEmoji" : null, - "blocks" : [ { - "type" : "header", - "blockId" : "0", - "text" : { - "type" : "plain_text", - "text" : "Payment report on 10-06-2023", - "emoji" : false - } - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "@channel", - "verbatim" : null - }, - "blockId" : "1", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "Second Entry entry — 100 000 000 RUB\\nFirst entry — 100 000 EUR", - "verbatim" : null - }, - "blockId" : "2", - "fields" : null, - "accessory" : { - "type" : "image", - "image_url" : "Test2", - "alt_text" : "Funny pic" - } - } ], - "attachments" : null, - "unfurlLinks" : null, - "unfurlMedia" : null, - "metadata" : null - }""", MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(payload)); + var report = iterator.next(); + assertEquals(Report.builder() + .header("Payment report on 10-06-2023") + .notifyChannel(true) + .build() + .addBody("Second Entry entry — 100 000 000 RUB\nFirst entry — 100 000 EUR", "Test2"), + report); } } \ No newline at end of file diff --git a/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/EmployeeEventReportMessageConverterTest.java b/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/EmployeeEventReportMessageConverterTest.java index 17bbe89d..83f2c277 100644 --- a/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/EmployeeEventReportMessageConverterTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/EmployeeEventReportMessageConverterTest.java @@ -1,17 +1,14 @@ package com.whiskels.notifier.reporting.service.employee.convert; -import com.slack.api.webhook.Payload; +import com.whiskels.notifier.reporting.service.Report; import com.whiskels.notifier.reporting.service.ReportData; import com.whiskels.notifier.reporting.service.employee.domain.Employee; -import com.whiskels.notifier.utilities.collections.StreamUtil; -import lombok.SneakyThrows; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import java.time.LocalDate; import java.util.List; -import static com.whiskels.notifier.JsonUtils.MAPPER; import static com.whiskels.notifier.MockedClockConfiguration.CLOCK; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; @@ -32,137 +29,28 @@ class EmployeeEventReportMessageConverterTest { @Test @DisplayName("Should convert employee payloads") void shouldConvertEmployeePayload() { - var expectedBirthday = """ - { - "threadTs" : null, - "text" : "Birthday Header", - "channel" : null, - "username" : null, - "iconUrl" : null, - "iconEmoji" : null, - "blocks" : [ { - "type" : "header", - "blockId" : "0", - "text" : { - "type" : "plain_text", - "text" : "Birthday Header", - "emoji" : false - } - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "@channel", - "verbatim" : null - }, - "blockId" : "1", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "Happy Birthday!", - "verbatim" : null - }, - "blockId" : "2", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "• Test 01.01", - "verbatim" : null - }, - "blockId" : "3", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "Happy Anniversary!", - "verbatim" : null - }, - "blockId" : "4", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "No Data", - "verbatim" : null - }, - "blockId" : "5", - "fields" : null, - "accessory" : null - } ], - "attachments" : null, - "unfurlLinks" : null, - "unfurlMedia" : null, - "metadata" : null - }"""; - var expectedAnniversary = """ - { - "threadTs" : null, - "text" : "Anniversary Header", - "channel" : null, - "username" : null, - "iconUrl" : null, - "iconEmoji" : null, - "blocks" : [ { - "type" : "header", - "blockId" : "0", - "text" : { - "type" : "plain_text", - "text" : "Anniversary Header", - "emoji" : false - } - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "@channel", - "verbatim" : null - }, - "blockId" : "1", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "Happy Anniversary!", - "verbatim" : null - }, - "blockId" : "2", - "fields" : null, - "accessory" : null - }, { - "type" : "section", - "text" : { - "type" : "mrkdwn", - "text" : "• Test 01.02 (2)", - "verbatim" : null - }, - "blockId" : "3", - "fields" : null, - "accessory" : null - } ], - "attachments" : null, - "unfurlLinks" : null, - "unfurlMedia" : null, - "metadata" : null - }"""; - ReportContext birthdayContext = mock(ReportContext.class); + var expectedBirthdayReport = Report.builder() + .header("Birthday Header") + .notifyChannel(true) + .build() + .addBody("Happy Birthday!") + .addBody("• Test 01.01") + .addBody("Happy Anniversary!") + .addBody("No Data"); + + var expectedAnniversary = Report.builder() + .header("Anniversary Header") + .notifyChannel(true) + .build() + .addBody("Happy Anniversary!") + .addBody("• Test 01.02 (2)"); + com.whiskels.notifier.reporting.service.employee.convert.ReportContext birthdayContext = mock(com.whiskels.notifier.reporting.service.employee.convert.ReportContext.class); when(birthdayContext.getSkipEmpty()).thenReturn(_ -> false); when(birthdayContext.getBirthdayPredicate()).thenReturn((_, _) -> true); when(birthdayContext.getAnniversaryPredicate()).thenReturn((_, _) -> false); when(birthdayContext.getHeaderMapper()).thenReturn(_ -> "Birthday Header"); - ReportContext anniversaryContext = mock(ReportContext.class); + com.whiskels.notifier.reporting.service.employee.convert.ReportContext anniversaryContext = mock(com.whiskels.notifier.reporting.service.employee.convert.ReportContext.class); when(anniversaryContext.getSkipEmpty()).thenReturn(_ -> true); when(anniversaryContext.getBirthdayPredicate()).thenReturn((_, _) -> false); when(anniversaryContext.getAnniversaryPredicate()).thenReturn((_, _) -> true); @@ -176,19 +64,17 @@ void shouldConvertEmployeePayload() { employee("Test", LocalDate.of(2000, 1, 1), LocalDate.of(2022, 2, 1)) ), LocalDate.now(CLOCK)); - Iterable payloads = converter.convert(reportData); - List payloadList = (List) payloads; + List payloads = (List) converter.convert(reportData); - assertFalse(payloadList.isEmpty()); - assertEquals(2, payloadList.size()); - assertThat(StreamUtil.map(payloadList, this::map)) - .containsExactly(expectedBirthday, expectedAnniversary); + assertFalse(payloads.isEmpty()); + assertEquals(2, payloads.size()); + assertThat(payloads).containsExactly(expectedBirthdayReport, expectedAnniversary); } @Test @DisplayName("Should return null if skip empty and no data") void shouldReturnNullIfSkipEmptyAndNoData() { - ReportContext context = mock(ReportContext.class); + com.whiskels.notifier.reporting.service.employee.convert.ReportContext context = mock(com.whiskels.notifier.reporting.service.employee.convert.ReportContext.class); when(context.getSkipEmpty()).thenReturn(_ -> true); when(context.getBirthdayPredicate()).thenReturn((_, _) -> false); when(context.getAnniversaryPredicate()).thenReturn((_, _) -> false); @@ -202,11 +88,6 @@ void shouldReturnNullIfSkipEmptyAndNoData() { assertFalse(actual.iterator().hasNext()); } - @SneakyThrows - private String map(Payload payload) { - return MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(payload); - } - private Employee employee(String name, LocalDate birthday, LocalDate appointment) { var employee = new Employee(); employee.setName(name); diff --git a/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/BeforeEventReportContextTest.java b/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/BeforeEventReportDataTest.java similarity index 92% rename from src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/BeforeEventReportContextTest.java rename to src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/BeforeEventReportDataTest.java index aa2094ba..f3c7e2c0 100644 --- a/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/BeforeEventReportContextTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/BeforeEventReportDataTest.java @@ -1,6 +1,5 @@ package com.whiskels.notifier.reporting.service.employee.convert.context; -import com.whiskels.notifier.reporting.service.employee.convert.context.BeforeEventReportContext; import com.whiskels.notifier.reporting.service.employee.domain.Employee; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -11,7 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -class BeforeEventReportContextTest { +class BeforeEventReportDataTest { @Test @DisplayName("Should initialize header") diff --git a/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/DailyReportContextTest.java b/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/DailyReportDataTest.java similarity index 98% rename from src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/DailyReportContextTest.java rename to src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/DailyReportDataTest.java index 0effb1b9..97c30b6a 100644 --- a/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/DailyReportContextTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/DailyReportDataTest.java @@ -10,7 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -class DailyReportContextTest { +class DailyReportDataTest { @Test @DisplayName("Should initialize header") diff --git a/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/MonthMiddleReportContextTest.java b/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/MonthMiddleReportDataTest.java similarity index 98% rename from src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/MonthMiddleReportContextTest.java rename to src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/MonthMiddleReportDataTest.java index 185bfa30..a6a2c5f3 100644 --- a/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/MonthMiddleReportContextTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/MonthMiddleReportDataTest.java @@ -10,7 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -class MonthMiddleReportContextTest { +class MonthMiddleReportDataTest { @Test @DisplayName("Should initialize header") diff --git a/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/MonthStartReportContextTest.java b/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/MonthStartReportDataTest.java similarity index 98% rename from src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/MonthStartReportContextTest.java rename to src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/MonthStartReportDataTest.java index 350f2308..94fb46e2 100644 --- a/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/MonthStartReportContextTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/service/employee/convert/context/MonthStartReportDataTest.java @@ -10,7 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -class MonthStartReportContextTest { +class MonthStartReportDataTest { @Test @DisplayName("Should initialize header") diff --git a/src/test/java/com/whiskels/notifier/reporting/service/employee/fetch/EmployeeDataFetchServiceTest.java b/src/test/java/com/whiskels/notifier/reporting/service/employee/fetch/EmployeeDataFetchServiceTest.java index fefdaf4e..2800d9c5 100644 --- a/src/test/java/com/whiskels/notifier/reporting/service/employee/fetch/EmployeeDataFetchServiceTest.java +++ b/src/test/java/com/whiskels/notifier/reporting/service/employee/fetch/EmployeeDataFetchServiceTest.java @@ -2,8 +2,6 @@ import com.whiskels.notifier.reporting.service.ReportData; import com.whiskels.notifier.reporting.service.employee.domain.Employee; -import com.whiskels.notifier.reporting.service.employee.fetch.EmployeeDataFetchService; -import com.whiskels.notifier.reporting.service.employee.fetch.EmployeeFeignClient; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test;