Skip to content

Commit

Permalink
Add possibility to set custom FreeMarker templates for messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrei Kliuchnikau committed Aug 6, 2024
1 parent 8da9401 commit d4ed89e
Show file tree
Hide file tree
Showing 27 changed files with 376 additions and 149 deletions.
178 changes: 178 additions & 0 deletions README.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
[![ru](https://img.shields.io/badge/lang-ru-red.svg)](https://github.com/qa-guru/allure-notifications/blob/master/README.md)

# Allure notifications
**Allure notifications** is the library that allows to send automatic notifications about the results of automated tests to your preferred messenger (Telegram, Slack, Skype, Email, Mattermost, Discord, Loop, Rocket.Chat).

Notification languages: 🇬🇧 🇫🇷 🇷🇺 🇺🇦 🇧🇾 🇨🇳

## Content
+ [How it works](#how-it-works)
+ [What the notifications look like](#what-the-notifications-look-like)
+ [How to use in your project](#how-to-use-in-your-project)


## How it works
After an autotest has finished its work, the `summary.json` file is generated in the `allure-report/widgets` folder. This file contains general statistic about the test results and uses to form the notification sent by the bot (the diagram is drawn and the corresponding text is added).

Example of a `summary.json` file
```
{
"reportName" : "Allure Report",
"testRuns" : [ ],
"statistic" : {
"failed" : 182,
"broken" : 70,
"skipped" : 118,
"passed" : 439,
"unknown" : 42,
"total" : 851
},
"time" : {
"start" : 1590795193703,
"stop" : 1590932641296,
"duration" : 11311,
"minDuration" : 7901,
"maxDuration" : 109870,
"sumDuration" : 150125
}
}
```

## What the notifications look like
Example of a notification in Telegram

![telegram](https://user-images.githubusercontent.com/109241600/213396660-c70adc4c-7a0f-4926-8d9d-473c6c433dd2.png)

## How to use in your project

1. Setup Java
2. Create `notifications` folder in the root of your project
3. Download [the latest version](https://github.com/qa-guru/allure-notifications/releases) of the `allure-notifications-<version>.jar` file and place it in the `notifications` folder in your project
4. In the `notifications` folder create the `config.json` file with the following structure (keep the base section and the messenger to which notifications need to be sent):
```
{
"base": {
"logo": "",
"project": "",
"environment": "",
"comment": "",
"reportLink": "",
"language": "ru",
"allureFolder": "",
"enableChart": false,
"templatePath": ""
},
"telegram": {
"token": "",
"chat": "",
"replyTo": "",
"templatePath": ""
},
"slack": {
"token": "",
"chat": "",
"replyTo": "",
"templatePath": ""
},
"mattermost": {
"url": "",
"token": "",
"chat": "",
"templatePath": ""
},
"rocketChat" : {
"url": "",
"auth_token": "",
"user_id": "",
"channel": "",
"templatePath": ""
},
"skype": {
"appId": "",
"appSecret": "",
"serviceUrl": "",
"conversationId": "",
"botId": "",
"botName": "",
"templatePath": ""
},
"mail": {
"host": "",
"port": "",
"username": "",
"password": "",
"securityProtocol": null,
"from": "",
"recipient": "",
"templatePath": ""
},
"discord": {
"botToken": "",
"channelId": "",
"templatePath": ""
},
"loop": {
"webhookUrl": "",
"templatePath": ""
},
"proxy": {
"host": "",
"port": 0,
"username": "",
"password": ""
}
}
```
The `proxy` block is used if you need to specify additional proxy configuration.\
Additionally, in any configuration you can specify the `templatePath` parameter to set the path to your own Freemarker template for the message.
```
{
"base": {
...
},
"mail": {
"host": "smtp.gmail.com",
"port": "465",
"username": "username",
"password": "password",
"securityProtocol": "SSL",
"from": "test@gmail.com",
"recipient": "test1@gmail.com",
"templatePath": "templates/html_custom.ftl"
}
}
```
5. Fill the `base` block in the `config.json` file

Example:
```
"base": {
"project": "some project",
"environment": "some env",
"comment": "some comment",
"reportLink": "",
"language": "en",
"allureFolder": "build/allure-report/",
"enableChart": true,
"logo": "logo.png",
"durationFormat": "HH:mm:ss.SSS"
}
```

Fields:
+ `project`, `environment`, `comment` - the name of the project, the name of the environment, and a custom comment.
+ `reportLink` - the link to the Allure report with results of tests.
+ `language` - the language in which the notification text will be formed (options: `en` / `fr` / `ru` / `ua` / `by` / `cn`).
+ `allureFolder` - the path to the folder with Allure results.
+ `enableChart` - whether the chart should be displayed (options: `true` / `false`).
+ `logo` - path to the logo file (if filled, the corresponding logo will be displayed in the top left corner of the chart).
+ `durationFormat` (optional, default value is `HH:mm:ss.SSS`) - specifies the desired output format for the test duration.
6. Fill in the `config.json` file block with the information about the chosen messenger.
7. Execute the following command in terminal:
```
java "-DconfigFile=notifications/config.json" -jar notifications/allure-notifications-4.6.1.jar
```
Note:

+ by the time of execution the `summary.json` file should already be generated.
+ in the command-line text you need to specify the version of the `jar` file that you downloaded in the previous steps.
50 changes: 40 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[![en](https://img.shields.io/badge/lang-en-red.svg)](https://github.com/qa-guru/allure-notifications/blob/master/README.en.md)

# Allure notifications
**Allure notifications** - это библиотека, позволяющая выполнять автоматическое оповещение о результатах прохождения автотестов, которое направляется в нужный вам мессенджер (Telegram, Slack, Skype, Email, Mattermost, Discord, Loop, Rocket.Chat).

Expand Down Expand Up @@ -75,36 +77,42 @@ Languages: 🇬🇧 🇫🇷 🇷🇺 🇺🇦 🇧🇾 🇨🇳
"reportLink": "",
"language": "ru",
"allureFolder": "",
"enableChart": false
"enableChart": false,
"templatePath": ""
},
"telegram": {
"token": "",
"chat": "",
"replyTo": ""
"replyTo": "",
"templatePath": ""
},
"slack": {
"token": "",
"chat": "",
"replyTo": ""
"replyTo": "",
"templatePath": ""
},
"mattermost": {
"url": "",
"token": "",
"chat": ""
"chat": "",
"templatePath": ""
},
"rocketChat" : {
"url": "",
"auth_token": "",
"user_id": "",
"channel": ""
"channel": "",
"templatePath": ""
},
"skype": {
"appId": "",
"appSecret": "",
"serviceUrl": "",
"conversationId": "",
"botId": "",
"botName": ""
"botName": "",
"templatePath": ""
},
"mail": {
"host": "",
Expand All @@ -113,14 +121,17 @@ Languages: 🇬🇧 🇫🇷 🇷🇺 🇺🇦 🇧🇾 🇨🇳
"password": "",
"securityProtocol": null,
"from": "",
"recipient": ""
"recipient": "",
"templatePath": ""
},
"discord": {
"botToken": "",
"channelId": ""
"channelId": "",
"templatePath": ""
},
"loop": {
"webhookUrl": ""
"webhookUrl": "",
"templatePath": ""
},
"proxy": {
"host": "",
Expand All @@ -130,7 +141,26 @@ Languages: 🇬🇧 🇫🇷 🇷🇺 🇺🇦 🇧🇾 🇨🇳
}
}
```
Блок `proxy` используется если нужно указать дополнительную конфигурацию proxy.
Блок `proxy` используется если нужно указать дополнительную конфигурацию proxy.\
Также в любой из конфигураций мессенджера можно дополнительно указать параметр `templatePath`, чтобы установить путь к собственному Freemarker шаблону для сообщения.
Пример:
```
{
"base": {
...
},
"mail": {
"host": "smtp.gmail.com",
"port": "465",
"username": "username",
"password": "password",
"securityProtocol": "SSL",
"from": "test@gmail.com",
"recipient": "test1@gmail.com",
"templatePath": "templates/html_custom.ftl"
}
}
```

<a name="Base"></a>

Expand Down
4 changes: 3 additions & 1 deletion allure-notifications-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ dependencies {

testImplementation('org.junit.jupiter:junit-jupiter:5.10.3')
testRuntimeOnly('org.junit.platform:junit-platform-launcher')
testImplementation('org.mockito:mockito-junit-jupiter:4.11.0')
testImplementation platform(group: 'org.mockito', name: 'mockito-bom', version: '4.11.0')
testImplementation(group: 'org.mockito', name: 'mockito-junit-jupiter')
testImplementation(group: 'org.mockito', name: 'mockito-inline')
}

tasks.withType(Test).configureEach {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import guru.qa.allure.notifications.clients.Notifier;
import guru.qa.allure.notifications.config.discord.Discord;
import guru.qa.allure.notifications.exceptions.MessagingException;
import guru.qa.allure.notifications.template.MarkdownTemplate;
import guru.qa.allure.notifications.template.MessageTemplate;
import guru.qa.allure.notifications.template.data.MessageData;
import kong.unirest.ContentType;
import kong.unirest.Unirest;
Expand All @@ -23,7 +23,7 @@ public void sendText(MessageData messageData) throws MessagingException {
.routeParam("channelId", discord.getChannelId())
.header("Authorization", "Bot " + discord.getBotToken())
.header("Content-Type", ContentType.APPLICATION_FORM_URLENCODED.getMimeType())
.field("content", new MarkdownTemplate(messageData).create())
.field("content", new MessageTemplate(messageData).createMessageFromTemplate(discord.getTemplatePath()))
.asString()
.getBody();
}
Expand All @@ -34,7 +34,7 @@ public void sendPhoto(MessageData messageData, byte[] chartImage) throws Messagi
.routeParam("channelId", discord.getChannelId())
.header("Authorization", "Bot " + discord.getBotToken())
.field("file", new ByteArrayInputStream(chartImage), ContentType.IMAGE_PNG, "chart.png")
.field("content", new MarkdownTemplate(messageData).create())
.field("content", new MessageTemplate(messageData).createMessageFromTemplate(discord.getTemplatePath()))
.asString()
.getBody();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import guru.qa.allure.notifications.clients.Notifier;
import guru.qa.allure.notifications.config.loop.Loop;
import guru.qa.allure.notifications.exceptions.MessagingException;
import guru.qa.allure.notifications.template.MarkdownTemplate;
import guru.qa.allure.notifications.template.MessageTemplate;
import guru.qa.allure.notifications.template.data.MessageData;
import kong.unirest.ContentType;
import kong.unirest.Unirest;
Expand All @@ -21,7 +21,7 @@ public LoopClient(Loop loop) {
@Override
public void sendText(MessageData messageData) throws MessagingException {
Map<String, Object> body = new HashMap<>();
body.put("text", new MarkdownTemplate(messageData).create());
body.put("text", new MessageTemplate(messageData).createMessageFromTemplate(loop.getTemplatePath()));

Unirest.post(loop.getWebhookUrl())
.header("Content-Type", ContentType.APPLICATION_JSON.getMimeType())
Expand All @@ -35,7 +35,7 @@ public void sendPhoto(MessageData messageData, byte[] chartImage) throws Messagi
String encodedChartImage = Base64.getEncoder().encodeToString(chartImage);

Map<String, Object> body = new HashMap<>();
body.put("text", new MarkdownTemplate(messageData).create());
body.put("text", new MessageTemplate(messageData).createMessageFromTemplate(loop.getTemplatePath()));

Map<String, String> attachment = new HashMap<>();
attachment.put("image_url", "data:image/png;base64," + encodedChartImage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import guru.qa.allure.notifications.clients.Notifier;
import guru.qa.allure.notifications.config.mail.Mail;
import guru.qa.allure.notifications.exceptions.MessagingException;
import guru.qa.allure.notifications.template.HTMLTemplate;
import guru.qa.allure.notifications.template.MessageTemplate;
import guru.qa.allure.notifications.template.data.MessageData;

public class Email implements Notifier {
Expand All @@ -20,13 +20,14 @@ public void sendText(MessageData messageData) throws MessagingException {
letter.from(mail.getFrom())
.to(mail.getRecipient())
.subject(messageData.getProject())
.text(new HTMLTemplate(messageData).create())
.text(new MessageTemplate(messageData).createMessageFromTemplate(mail.getTemplatePath()))
.send();
}

@Override
public void sendPhoto(MessageData messageData, byte[] chartImage) throws MessagingException {
String message = "<img src='cid:image'/><br/>" + new HTMLTemplate(messageData).create();
String message = "<img src='cid:image'/><br/>" + new MessageTemplate(messageData).createMessageFromTemplate(
mail.getTemplatePath());
letter.from(mail.getFrom())
.to(mail.getRecipient())
.subject(messageData.getProject())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import guru.qa.allure.notifications.config.mattermost.Mattermost;
import guru.qa.allure.notifications.exceptions.MessageBuildException;
import guru.qa.allure.notifications.exceptions.MessagingException;
import guru.qa.allure.notifications.template.MarkdownTemplate;
import guru.qa.allure.notifications.template.MessageTemplate;
import kong.unirest.ContentType;
import guru.qa.allure.notifications.template.data.MessageData;
import kong.unirest.Unirest;
Expand Down Expand Up @@ -48,7 +48,7 @@ public void sendPhoto(MessageData messageData, byte[] chartImage) throws Messagi

private void send(MessageData messageData, Map<String, Object> body) throws MessageBuildException {
body.put("channel_id", mattermost.getChat());
body.put("message", new MarkdownTemplate(messageData).create());
body.put("message", new MessageTemplate(messageData).createMessageFromTemplate(mattermost.getTemplatePath()));

Unirest.post("https://{uri}/api/v4/posts")
.routeParam("uri", mattermost.getUrl())
Expand Down
Loading

0 comments on commit d4ed89e

Please sign in to comment.