Skip to content

Commit 82e75af

Browse files
authored
Merge pull request #184 from contentstack/fix/DX-2420-pipeline-friendly
Fixed testcase assertions to be env agnostic
2 parents c62265f + 9448814 commit 82e75af

18 files changed

+340
-176
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ local.properties
2525
.settings/
2626
.loadpath
2727
.recommenders
28+
# Ignore test configuration
29+
test-config.properties
2830

2931
# External tool builders
3032
.externalToolBuilders/

pom.xml

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<dotenv-source.version>3.0.0</dotenv-source.version>
2323
<rxjava-source.version>3.1.10</rxjava-source.version>
2424
<retrofit-source.version>2.11.0</retrofit-source.version>
25-
<loggin.version>5.0.0-alpha.11</loggin.version>
25+
<loggin.version>4.12.0</loggin.version>
2626
<jococo-plugin.version>0.8.5</jococo-plugin.version>
2727
<lombok-source.version>1.18.36</lombok-source.version>
2828
<junit-jupiter.version>5.11.4</junit-jupiter.version>
@@ -34,7 +34,7 @@
3434
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
3535
<nexus-staging-maven-plugin.version>1.6.13</nexus-staging-maven-plugin.version>
3636
<json-version>20250107</json-version>
37-
<jacoco-maven-plugin-version>0.8.7</jacoco-maven-plugin-version>
37+
<jacoco-maven-plugin-version>0.8.11</jacoco-maven-plugin-version>
3838
<maven-release-plugin-version>2.5.3</maven-release-plugin-version>
3939
<contentstack-utils-version>1.2.15</contentstack-utils-version>
4040
</properties>
@@ -122,14 +122,6 @@
122122
<scope>compile</scope>
123123
</dependency>
124124

125-
<!-- https://mvnrepository.com/artifact/io.github.cdimascio/java-dotenv -->
126-
<dependency>
127-
<groupId>io.github.cdimascio</groupId>
128-
<artifactId>java-dotenv</artifactId>
129-
<version>5.2.2</version>
130-
</dependency>
131-
132-
133125
<dependency>
134126
<groupId>io.reactivex.rxjava3</groupId>
135127
<artifactId>rxjava</artifactId>
@@ -189,6 +181,27 @@
189181
<artifactId>jackson-databind</artifactId>
190182
<version>2.18.2</version>
191183
</dependency>
184+
<dependency>
185+
<groupId>com.slack.api</groupId>
186+
<artifactId>bolt</artifactId>
187+
<version>1.44.0</version>
188+
</dependency>
189+
<dependency>
190+
<groupId>org.jetbrains</groupId>
191+
<artifactId>annotations</artifactId>
192+
<version>24.0.1</version>
193+
</dependency>
194+
<dependency>
195+
<groupId>com.squareup.okhttp3</groupId>
196+
<artifactId>okhttp</artifactId>
197+
<version>4.12.0</version>
198+
</dependency>
199+
<dependency>
200+
<groupId>org.slf4j</groupId>
201+
<artifactId>slf4j-simple</artifactId>
202+
<version>1.7.36</version>
203+
</dependency>
204+
192205
</dependencies>
193206

194207
<build>
@@ -237,8 +250,7 @@
237250
<use>false</use>
238251
<source>1.8</source>
239252
<links>
240-
<link>https://docs.oracle.com/javase/7/docs/api/</link>
241-
<link>https://docs.oracle.com/javase/7/docs/api/</link>
253+
<link>https://docs.oracle.com/en/java/javase/23/docs/api/index.html</link>
242254
</links>
243255
<doclint>none</doclint>
244256
</configuration>
@@ -251,7 +263,7 @@
251263
<artifactId>maven-surefire-plugin</artifactId>
252264
<version>2.22.2</version>
253265
<configuration>
254-
<skipTests>true</skipTests>
266+
<!-- <skipTests>true</skipTests> -->
255267
</configuration>
256268
</plugin>
257269

send-report.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
3+
set -e # Exit immediately if any command fails
4+
5+
echo "🧪 Running tests..."
6+
mvn clean test
7+
8+
echo "📄 Generating Surefire HTML report..."
9+
mvn surefire-report:report-only
10+
11+
echo "📤 Sending test report to Slack..."
12+
mvn compile exec:java -Dexec.mainClass="com.contentstack.sdk.SanityReport"
13+
14+
echo "✅ Done."

src/main/java/com/contentstack/sdk/CSHttpConnection.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ private String getParams(HashMap<String, Object> params) {
158158
urlParams += urlParams.equals("?") ? key + "=" + value : "&" + key + "=" + value;
159159
}
160160
} catch (Exception e1) {
161-
e1.printStackTrace();
161+
logger.log(Level.SEVERE, e1.getLocalizedMessage(), e1);
162162
}
163163
}
164164
return urlParams;

src/main/java/com/contentstack/sdk/Entry.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ private void setIncludeJSON(JSONObject mainJson, ResultCallBack callBack) {
995995

996996
private void throwException(@Nullable String errorMsg, Exception e, EntryResultCallBack callBack) {
997997
Error error = new Error();
998-
if (errorMsg != null) {
998+
if (!errorMsg.isEmpty()) {
999999
error.setErrorMessage(errorMsg);
10001000
} else {
10011001
error.setErrorMessage(e.toString());
@@ -1124,11 +1124,9 @@ public Entry includeMetadata() {
11241124
}
11251125

11261126
/**
1127-
* @method variants
1128-
* @memberof Entry
1129-
* @description The variant header will be added to client
1130-
* @returns {Entry}
1131-
* @example
1127+
* The variant header will be added to client
1128+
* @return {Entry}
1129+
*
11321130
* import contentstack from '@contentstack/delivery-sdk'
11331131
*
11341132
* Stack stack = contentstack.Stack("apiKey", "deliveryToken",
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package com.contentstack.sdk;
2+
import java.io.File;
3+
import java.io.FileInputStream;
4+
import java.io.IOException;
5+
import java.util.Properties;
6+
import org.jsoup.Jsoup;
7+
import org.jsoup.nodes.Document;
8+
import org.jsoup.nodes.Element;
9+
import org.jsoup.select.Elements;
10+
import com.slack.api.bolt.App;
11+
import com.slack.api.methods.SlackApiException;
12+
import com.slack.api.methods.response.chat.ChatPostMessageResponse;
13+
import com.slack.api.methods.response.files.FilesUploadV2Response;
14+
15+
public class SanityReport {
16+
17+
private static final String PROPERTIES_FILE = "src/test/resources/test-config.properties";
18+
19+
public void generateTestSummaryAndSendToSlack(File reportFile) throws IOException, SlackApiException {
20+
Properties properties = loadProperties(PROPERTIES_FILE);
21+
22+
String slackToken = properties.getProperty("SLACK_BOT_TOKEN");
23+
String slackChannelID = properties.getProperty("SLACK_CHANNEL_ID");
24+
String signingSecret = properties.getProperty("SLACK_SIGNING_SECRET");
25+
String slackChannel = properties.getProperty("SLACK_CHANNEL");
26+
27+
if (slackToken == null || slackChannelID == null) {
28+
System.err.println("Missing Slack credentials in properties.");
29+
return;
30+
}
31+
32+
if (!reportFile.exists()) {
33+
System.err.println("Surefire report file not found at: " + reportFile.getAbsolutePath());
34+
return;
35+
}
36+
37+
String message = generateTestSummary(reportFile);
38+
App app = configureSlackApp(slackToken, signingSecret);
39+
40+
sendMessageToSlack(app, slackChannel, message);
41+
uploadReportToSlack(app, slackChannelID, reportFile);
42+
}
43+
44+
private Properties loadProperties(String filePath) {
45+
Properties properties = new Properties();
46+
try (FileInputStream inputStream = new FileInputStream(filePath)) {
47+
properties.load(inputStream);
48+
} catch (IOException e) {
49+
System.err.println("Failed to load properties: " + e.getMessage());
50+
}
51+
return properties;
52+
}
53+
54+
private App configureSlackApp(String token, String secret) {
55+
App app = new App();
56+
app.config().setSigningSecret(secret);
57+
app.config().setSingleTeamBotToken(token);
58+
return app;
59+
}
60+
61+
private void sendMessageToSlack(App app, String channel, String message) throws IOException, SlackApiException {
62+
ChatPostMessageResponse response = app.client().chatPostMessage(r -> r
63+
.channel(channel)
64+
.text(message)
65+
);
66+
if (response.isOk()) {
67+
System.out.println("Message sent successfully!");
68+
} else {
69+
System.err.println("Failed to send message: " + response.getError());
70+
}
71+
}
72+
73+
private void uploadReportToSlack(App app, String channelID, File file) throws IOException, SlackApiException {
74+
FilesUploadV2Response response = app.client().filesUploadV2(fuvr -> fuvr
75+
.channel(channelID)
76+
.initialComment("Here is the report generated")
77+
.filename(file.getName())
78+
.file(file)
79+
);
80+
if (response.isOk()) {
81+
System.out.println("Report uploaded successfully!");
82+
} else {
83+
System.err.println("Failed to upload report: " + response.getError());
84+
}
85+
86+
}
87+
88+
private String generateTestSummary(File surefireReportFile) throws IOException {
89+
Document doc = Jsoup.parse(surefireReportFile, "UTF-8");
90+
Elements summaryRows = doc.select("table.table tr.b");
91+
Element summaryRow = summaryRows.first();
92+
93+
int totalTests = 0, errors = 0, failures = 0, skipped = 0, passedTests, totalSuites, failedSuites = 0;
94+
String duration = "0m 0s";
95+
96+
if (summaryRow != null) {
97+
Elements cells = summaryRow.select("td");
98+
if (cells.size() >= 6) {
99+
totalTests = Integer.parseInt(cells.get(0).text());
100+
errors = Integer.parseInt(cells.get(1).text());
101+
failures = Integer.parseInt(cells.get(2).text());
102+
skipped = Integer.parseInt(cells.get(3).text());
103+
104+
String timeText = cells.get(5).text();
105+
if (timeText.contains("s")) {
106+
double seconds = Double.parseDouble(timeText.replace(" s", ""));
107+
duration = (int) seconds / 60 + "m " + (int) seconds % 60 + "s";
108+
}
109+
}
110+
}
111+
112+
Elements testSuiteRows = doc.select("table:contains(Class) tr");
113+
totalSuites = testSuiteRows.size() - 1;
114+
115+
for (Element row : testSuiteRows) {
116+
Elements errorCells = row.select("td:nth-child(4)");
117+
Elements failureCells = row.select("td:nth-child(5)");
118+
if (!errorCells.isEmpty() && !failureCells.isEmpty()) {
119+
try {
120+
if (Integer.parseInt(errorCells.text()) > 0 || Integer.parseInt(failureCells.text()) > 0) {
121+
failedSuites++;
122+
}
123+
} catch (NumberFormatException ignored) {
124+
}
125+
}
126+
}
127+
128+
passedTests = totalTests - failures - errors - skipped;
129+
130+
return "*Java CDA Test Report*\n"
131+
+ "• Total Suites: " + totalSuites + "\n"
132+
+ "• Total Tests: " + totalTests + "\n"
133+
+ "• Passed Tests: " + passedTests + "\n"
134+
+ "• Failed Suites: " + failedSuites + "\n"
135+
+ "• Failed Tests: " + failures + "\n"
136+
+ "• Skipped Tests: " + skipped + "\n"
137+
+ "• Duration: " + duration;
138+
}
139+
140+
public static void main(String[] args) {
141+
File reportFile = new File("target/reports/surefire.html");
142+
try {
143+
new SanityReport().generateTestSummaryAndSendToSlack(reportFile);
144+
} catch (IOException | SlackApiException e) {
145+
System.err.println("Error: " + e.getMessage());
146+
}
147+
}
148+
149+
}

src/main/java/com/contentstack/sdk/Stack.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ private void includeLivePreview() {
103103
if (config.enableLivePreview) {
104104
String urlLivePreview = config.livePreviewHost;
105105
if(config.region != null && !config.region.name().isEmpty()){
106-
if(config.region.name() == "US" ){
106+
if(config.region.name().equals("US") ){
107107
config.livePreviewHost = urlLivePreview;
108108
}else{
109109
String regionPrefix = config.region.name().toLowerCase();

src/main/java/com/contentstack/sdk/Taxonomy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* Taxonomy, currently in the Early Access Phase simplifies
1818
* the process of organizing content in your system, making
1919
* it effortless to find and retrieve information.
20-
* @implSpec To implement the taxonomy use below code
20+
* To implement the taxonomy use below code
2121
* <pre>
2222
* {@code
2323
* Stack stack = Contentstack.stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT");

src/test/java/com/contentstack/sdk/Credentials.java

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package com.contentstack.sdk;
22

3-
import io.github.cdimascio.dotenv.Dotenv;
4-
3+
import java.io.FileInputStream;
4+
import java.io.IOException;
55
import java.rmi.AccessException;
66
import java.util.Arrays;
7+
import java.util.Properties;
78

89
public class Credentials {
9-
static Dotenv env = getEnv();
10+
private static final Properties properties = new Properties();
1011

1112
private static String envChecker() {
1213
String githubActions = System.getenv("GITHUB_ACTIONS");
@@ -17,25 +18,24 @@ private static String envChecker() {
1718
}
1819
}
1920

20-
public static Dotenv getEnv() {
21-
env = Dotenv.configure()
22-
.directory("src/test/resources")
23-
.filename("env") // instead of '.env', use 'env'
24-
.load();
25-
26-
return Dotenv.load();
21+
static {
22+
try (FileInputStream inputStream = new FileInputStream("src/test/resources/test-config.properties")) {
23+
properties.load(inputStream);
24+
} catch (IOException e) {
25+
System.err.println("Error loading properties file: " + e.getMessage());
26+
}
2727
}
2828

29-
public final static String HOST = (env.get("HOST") != null) ? env.get("HOST") : "cdn.contentstack.io";
30-
public final static String API_KEY = (env.get("API_KEY") != null) ? env.get("API_KEY") : "";
31-
public final static String DELIVERY_TOKEN = (env.get("DELIVERY_TOKEN") != null) ? env.get("DELIVERY_TOKEN") : "";
32-
public final static String ENVIRONMENT = (env.get("ENVIRONMENT") != null) ? env.get("ENVIRONMENT") : "env1";
33-
public final static String CONTENT_TYPE = (env.get("contentType") != null) ? env.get("contentType") : "product";
34-
public final static String ENTRY_UID = (env.get("assetUid") != null) ? env.get("assetUid") : "";
35-
public final static String VARIANT_UID = (env.get("variantUid") != null) ? env.get("variantUid") : "";
29+
public static final String HOST = properties.getProperty("HOST", "cdn.contentstack.io");
30+
public static final String API_KEY = properties.getProperty("API_KEY", "");
31+
public static final String DELIVERY_TOKEN = properties.getProperty("DELIVERY_TOKEN", "");
32+
public static final String ENVIRONMENT = properties.getProperty("ENVIRONMENT", "env1");
33+
public static final String CONTENT_TYPE = properties.getProperty("contentType", "product");
34+
public static final String ENTRY_UID = properties.getProperty("assetUid", "");
35+
public static final String VARIANT_UID = properties.getProperty("variantUid", "");
3636
public final static String[] VARIANTS_UID;
3737
static {
38-
String variantsUidString = env.get("variantsUid");
38+
String variantsUidString = properties.getProperty("variantsUid");
3939

4040
if (variantsUidString != null && !variantsUidString.trim().isEmpty()) {
4141
VARIANTS_UID = Arrays.stream(variantsUidString.split(","))

src/test/java/com/contentstack/sdk/TaxonomyTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
public class TaxonomyTest {
1414

1515
private final Stack stack = Credentials.getStack();
16+
private final String host = Credentials.HOST;
1617

1718
@Test
1819
void testInstance() {
@@ -28,7 +29,7 @@ void operationIn() {
2829
Request req = taxonomy.in("taxonomies.color", listOfItems).makeRequest().request();
2930
//Assertions.assertEquals(3, req.headers().size());
3031
Assertions.assertEquals("GET", req.method());
31-
Assertions.assertEquals("cdn.contentstack.io", req.url().host());
32+
Assertions.assertEquals(host, req.url().host());
3233
Assertions.assertEquals("/v3/taxonomies/entries", req.url().encodedPath());
3334
Assertions.assertEquals("query={\"taxonomies.color\":{\"$in\":[\"red\",\"yellow\"]}}", req.url().query());
3435
}

0 commit comments

Comments
 (0)