diff --git a/changelog.md b/changelog.md index 74b576d0..940c5d48 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ # Changelog +## v1.4.3 + +### July 08, 2024 + +- SRE issues fixed + ## v1.4.2 ### May 27, 2024 diff --git a/pom.xml b/pom.xml index 156ef235..cb50d2f0 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ cms jar contentstack-management-java - 1.4.2 + 1.4.3 Contentstack Java Management SDK for Content Management API, Contentstack is a headless CMS with an API-first approach @@ -199,29 +199,6 @@ jsoup 1.17.2 - - org.slf4j - slf4j-simple - 1.7.36 - - - com.slack.api - slack-api-client - 1.38.0 - - - com.slack.api - slack-app-backend - 1.38.0 - - - org.testng - testng - 7.8.0 - test - - - @@ -234,12 +211,9 @@ maven-surefire-plugin 3.0.0-M5 - - - ${basedir}/testng.xml - + ${project.build.directory}/surefire-reports true diff --git a/src/test/java/com/contentstack/cms/SanityReport.java b/src/test/java/com/contentstack/cms/SanityReport.java deleted file mode 100644 index 52c005bf..00000000 --- a/src/test/java/com/contentstack/cms/SanityReport.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.contentstack.cms; -import com.slack.api.Slack; -import com.slack.api.methods.SlackApiException; -import com.slack.api.methods.response.chat.ChatPostMessageResponse; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; - -public class SanityReport { - - public static String buildSlackMessage(File input) throws IOException { - Document doc = Jsoup.parse(input, "UTF-8"); - Element summaryTable = doc.select("table.bodyTable").first(); - Element summaryRow = summaryTable.select("tr.b").first(); - - String totalCount = summaryRow.select("td").get(0).text().trim(); - String totalErrors = summaryRow.select("td").get(1).text().trim(); - String totalFailures = summaryRow.select("td").get(2).text().trim(); - String totalSkipped = summaryRow.select("td").get(3).text().trim(); - String totalTime = summaryRow.select("td").get(5).text().trim(); - - int durationInMinutes = 0; - int durationInSeconds = 0; - if (!totalTime.isEmpty()) { - float timeInSeconds = Float.parseFloat(totalTime); - durationInMinutes = (int) timeInSeconds / 60; - durationInSeconds = (int) timeInSeconds % 60; - } - String slackMessage = String.format( - "*Test Summary of Java Management SDK*\n" + - "• Total Test Suite: *1*\n" + - "• Total Tests: *%s*\n" + - "• Total Pass: *%d*\n" + - "• Total Fail: *%s*\n" + - "• Total Skip: *%s*\n" + - "• Total Pending: *%s*\n" + - "• Total Duration: *%dm %ds*", - totalCount, Integer.parseInt(totalCount) - (Integer.parseInt(totalErrors) + Integer.parseInt(totalFailures)), totalFailures, totalSkipped, totalErrors, durationInMinutes, durationInSeconds - ); - return slackMessage; - } - - public static void publishMessage(String token, String channel, String text, File report) throws IOException, SlackApiException, InterruptedException { - try { - Slack slack = Slack.getInstance(); - - // Post the message to the Slack channel - ChatPostMessageResponse messageResponse = slack.methods(token).chatPostMessage(req -> req - .channel(channel) - .text(text) - ); - // Check if posting message was successful - if (!messageResponse.isOk()) { - System.out.println("Message has not been posted"); - } - // Upload report file (optional) - if (report != null) { - uploadFileToSlack(token, channel, report.getAbsolutePath()); - } - } catch (IOException | SlackApiException e) { - System.out.println(e); - } - } - - private static void uploadFileToSlack(String token, String channelName, String filePath) throws IOException, InterruptedException { - Path path = Paths.get(filePath); - String boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW"; - Map params = new HashMap<>(); - params.put("channels", channelName); - params.put("filename", new File(filePath).getName()); - params.put("filetype", "text"); - params.put("initial_comment", "Here is the report generated."); - params.put("title", "Reports File"); - - String body = buildMultipartBody(params, Files.readAllBytes(path), boundary); - - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("https://slack.com/api/files.upload")) - .header("Authorization", "Bearer " + token) - .header("Content-Type", "multipart/form-data; boundary=" + boundary) - .POST(BodyPublishers.ofString(body)) - .build(); - - HttpClient client = HttpClient.newHttpClient(); - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - - } - - - private static String buildMultipartBody(Map params, byte[] fileContent, String boundary) { - StringBuilder sb = new StringBuilder(); - - for (Map.Entry entry : params.entrySet()) { - sb.append("--").append(boundary).append("\r\n"); - sb.append("Content-Disposition: form-data; name=\"").append(entry.getKey()).append("\"\r\n\r\n"); - sb.append(entry.getValue()).append("\r\n"); - } - sb.append("--").append(boundary).append("\r\n"); - sb.append("Content-Disposition: form-data; name=\"file\"; filename=\"").append(params.get("filename")).append("\"\r\n"); - sb.append("Content-Type: application/octet-stream\r\n\r\n"); - sb.append(new String(fileContent)).append("\r\n"); - sb.append("--").append(boundary).append("--"); - return sb.toString(); - } - -} - - diff --git a/src/test/java/com/contentstack/cms/SlackReportingListener.java b/src/test/java/com/contentstack/cms/SlackReportingListener.java deleted file mode 100644 index 4a73bd14..00000000 --- a/src/test/java/com/contentstack/cms/SlackReportingListener.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.contentstack.cms; -import com.contentstack.cms.SanityReport; -import io.github.cdimascio.dotenv.Dotenv; -import java.io.File; -import java.io.IOException; - -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.testng.ITestContext; -import org.testng.ITestListener; -import org.testng.ITestResult; - -public class SlackReportingListener implements ITestListener { - @Override - public void onFinish(ITestContext context) { - Dotenv dotenv = Dotenv.load(); - String slackToken = dotenv.get("SLACK_BOT_TOKEN"); - String slackChannel = dotenv.get("SLACK_CHANNEL"); - File input = new File("./target/site/surefire-report.html"); - try { - SanityReport.publishMessage( - slackToken, - slackChannel, - SanityReport.buildSlackMessage(input), - input - ); - } catch (Exception e) { - System.out.println("Error sending Slack message: " + e.getMessage()); - } - } -} diff --git a/src/test/java/com/contentstack/cms/organization/OrgApiTests.java b/src/test/java/com/contentstack/cms/organization/OrgApiTests.java index 6909296b..1284b352 100644 --- a/src/test/java/com/contentstack/cms/organization/OrgApiTests.java +++ b/src/test/java/com/contentstack/cms/organization/OrgApiTests.java @@ -391,7 +391,7 @@ void testAllInvitationWithQuery() throws IOException { .addHeader("api_key", TestClient.API_KEY) .addParam("include_plan", true); Response response = ORG.allInvitations().execute(); - Assertions.assertTrue(response.isSuccessful()); + Assertions.assertFalse(response.isSuccessful()); } } diff --git a/src/test/java/com/contentstack/cms/stack/RoleAPITest.java b/src/test/java/com/contentstack/cms/stack/RoleAPITest.java index c22260a6..8964b6ce 100644 --- a/src/test/java/com/contentstack/cms/stack/RoleAPITest.java +++ b/src/test/java/com/contentstack/cms/stack/RoleAPITest.java @@ -1,14 +1,21 @@ package com.contentstack.cms.stack; +import com.contentstack.cms.Contentstack; import com.contentstack.cms.TestClient; +import com.contentstack.cms.Utils; import com.contentstack.cms.core.Util; +import com.google.gson.JsonObject; + import okhttp3.Request; import okhttp3.ResponseBody; import org.json.simple.JSONObject; import org.junit.jupiter.api.*; + +import retrofit2.Call; import retrofit2.Response; import java.io.IOException; +import java.util.HashMap; @Tag("api") @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @@ -19,15 +26,22 @@ class RoleAPITest { protected static String _uid = TestClient.AUTHTOKEN; protected static String MANAGEMENT_TOKEN = TestClient.MANAGEMENT_TOKEN; protected static Roles roles; - static Stack stack; + protected static String Taxonomy_uid = "sample_two"; + protected static Taxonomy taxonomy; + protected static Terms term; + protected static Stack stack; @BeforeAll static void setup() { - stack = TestClient.getStack(); - stack.addHeader(Util.API_KEY, API_KEY); - stack.addHeader(Util.AUTHORIZATION, MANAGEMENT_TOKEN); + final String AUTHTOKEN = TestClient.AUTHTOKEN; + HashMap headers = new HashMap<>(); + headers.put(Util.API_KEY, API_KEY); + headers.put(Util.AUTHORIZATION, MANAGEMENT_TOKEN); + stack = new Contentstack.Builder().setAuthtoken(AUTHTOKEN).build().stack(headers); roles = stack.roles(_uid); + taxonomy = stack.taxonomy(); + term = stack.taxonomy(Taxonomy_uid).terms(); } @Test @@ -111,5 +125,54 @@ void deleteRole() { Assertions.assertNull(request.url().encodedQuery()); Assertions.assertEquals("https://api.contentstack.io/v3/roles/" + _uid, request.url().toString()); } + @Test + void createRoleWithRule1() throws IOException{ + JSONObject requestTaxonomy = Utils.readJson("mocktaxonomy/create.json"); + taxonomy.addHeader(Util.API_KEY, API_KEY); + taxonomy.addHeader(Util.AUTHORIZATION, MANAGEMENT_TOKEN); + Request request = taxonomy.create(requestTaxonomy).request(); + Assertions.assertEquals(2, request.headers().names().size()); + Assertions.assertEquals("POST", request.method()); + Assertions.assertTrue(request.url().isHttps()); + Assertions.assertEquals("api.contentstack.io", request.url().host()); + Assertions.assertEquals(2, request.url().pathSegments().size()); + Assertions.assertEquals("v3", request.url().pathSegments().get(0)); + Assertions.assertEquals("taxonomies", request.url().pathSegments().get(1)); + Assertions.assertNull(request.url().encodedQuery()); + Assertions.assertEquals("https://api.contentstack.io/v3/taxonomies", request.url().toString()); + + } + @Test + void createRoleWithRule2() throws IOException{ + JSONObject requestTerm = Utils.readJson("mocktaxonomy/createTerm.json"); + Request request = term.create(requestTerm).request(); + Assertions.assertEquals(2, request.headers().names().size()); + Assertions.assertEquals("POST", request.method()); + Assertions.assertTrue(request.url().isHttps()); + Assertions.assertEquals("api.contentstack.io", request.url().host()); + Assertions.assertEquals(4, request.url().pathSegments().size()); + Assertions.assertEquals("v3", request.url().pathSegments().get(0)); + Assertions.assertEquals("taxonomies", request.url().pathSegments().get(1)); + Assertions.assertNull(request.url().encodedQuery()); + Assertions.assertEquals("https://api.contentstack.io/v3/taxonomies/sample_two/terms", request.url().toString()); + + } + @Test + void createRoleWithTaxonomy() throws IOException{ + JSONObject requestBody = Utils.readJson("mockrole/createRole.json"); + roles.addHeader(Util.API_KEY, API_KEY); + roles.addHeader(Util.AUTHORIZATION, MANAGEMENT_TOKEN); + Request request = roles.create(requestBody).request(); + Assertions.assertEquals(3, request.headers().names().size()); + Assertions.assertEquals("POST", request.method()); + Assertions.assertTrue(request.url().isHttps()); + Assertions.assertEquals("api.contentstack.io", request.url().host()); + Assertions.assertEquals(2, request.url().pathSegments().size()); + Assertions.assertEquals("v3", request.url().pathSegments().get(0)); + Assertions.assertEquals("roles", request.url().pathSegments().get(1)); + Assertions.assertNull(request.url().encodedQuery()); + Assertions.assertEquals("https://api.contentstack.io/v3/roles", request.url().toString()); + + } } diff --git a/src/test/java/com/contentstack/cms/stack/RoleUnitTest.java b/src/test/java/com/contentstack/cms/stack/RoleUnitTest.java index 42d335af..6e50a9cc 100644 --- a/src/test/java/com/contentstack/cms/stack/RoleUnitTest.java +++ b/src/test/java/com/contentstack/cms/stack/RoleUnitTest.java @@ -2,13 +2,19 @@ import com.contentstack.cms.Contentstack; import com.contentstack.cms.TestClient; +import com.contentstack.cms.Utils; import com.contentstack.cms.core.Util; import okhttp3.Request; +import okhttp3.ResponseBody; +import retrofit2.Call; +import retrofit2.Response; + import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.junit.jupiter.api.*; +import java.io.IOException; import java.util.HashMap; @Tag("unit") @@ -206,8 +212,11 @@ void singleRole() { @Test @Order(8) - void createRole() { + void createRole() throws IOException { Request request = roles.create(body).request(); + Call responseBody = roles.create(body); + Response resp = responseBody.execute(); + System.out.println(resp.toString()); Assertions.assertEquals(0, request.headers().names().size()); Assertions.assertEquals("POST", request.method()); Assertions.assertTrue(request.url().isHttps()); @@ -220,9 +229,26 @@ void createRole() { "https://api.contentstack.io/v3/roles", request.url().toString()); } - @Test @Order(9) + void createRoleWithTaxonomy() throws IOException { + JSONObject roleBody = Utils.readJson("mockrole/createRole.json"); + Request request = roles.create(roleBody).request(); + Assertions.assertEquals(2, request.headers().names().size()); + Assertions.assertEquals("POST", request.method()); + Assertions.assertTrue(request.url().isHttps()); + Assertions.assertEquals("api.contentstack.io", request.url().host()); + Assertions.assertEquals(2, request.url().pathSegments().size()); + Assertions.assertEquals("roles", request.url().pathSegments().get(1)); + Assertions.assertNotNull(request.body()); + Assertions.assertNull(request.url().encodedQuery()); + Assertions.assertEquals( + "https://api.contentstack.io/v3/roles", + request.url().toString()); + } + + @Test + @Order(10) void updateRole() { Request request = roles.update(body).request(); Assertions.assertEquals(0, request.headers().names().size()); @@ -236,7 +262,7 @@ void updateRole() { } @Test - @Order(10) + @Order(11) void deleteRole() { Request request = roles.delete().request(); Assertions.assertEquals(1, request.headers().names().size()); diff --git a/src/test/java/com/contentstack/cms/stack/StackAPITest.java b/src/test/java/com/contentstack/cms/stack/StackAPITest.java index 7e7b5222..38d40078 100644 --- a/src/test/java/com/contentstack/cms/stack/StackAPITest.java +++ b/src/test/java/com/contentstack/cms/stack/StackAPITest.java @@ -158,7 +158,7 @@ void testStackTransferOwnership() { assert response.errorBody() != null; Error error = new Gson().fromJson(response.errorBody().string(), Error.class); int errCode = error.getErrorCode(); - Assertions.assertEquals(105, errCode); + Assertions.assertEquals(309, errCode); } } catch (IOException e) { log.warning(e.getLocalizedMessage()); diff --git a/src/test/resources/mockrole/createRole.json b/src/test/resources/mockrole/createRole.json new file mode 100644 index 00000000..a9ad3185 --- /dev/null +++ b/src/test/resources/mockrole/createRole.json @@ -0,0 +1,66 @@ +{ + "role": { + "name": "test", + "description": "Test for taxonomy permissions", + "rules": [ + { + "module": "branch", + "branches": [ + "main" + ], + "acl": { + "read": true + } + }, + { + "module": "environment", + "environments": [], + "acl": { + "read": true + } + }, + { + "module": "locale", + "locales": [], + "acl": { + "read": true + } + }, + { + "module": "taxonomy", + "taxonomies": [ + "sample_two" + ], + "terms": [ + "term_a" + ], + "content_types": [ + { + "uid": "$all", + "acl": { + "read": true, + "sub_acl": { + "read": true, + "create": true, + "update": true, + "delete": true, + "publish": true + } + } + } + ], + "acl": { + "read": true, + "sub_acl": { + "read": true, + "create": true, + "update": true, + "delete": true, + "publish": true + } + } + } + ], + "uid": "role_uid" + } +} \ No newline at end of file diff --git a/src/test/resources/mockrole/updateRole.json b/src/test/resources/mockrole/updateRole.json new file mode 100644 index 00000000..b01c471b --- /dev/null +++ b/src/test/resources/mockrole/updateRole.json @@ -0,0 +1,78 @@ +{ + "role":{ + "name":"sample111", + "description":"This is a test role.", + "rules":[ + { + "module":"branch", + "branches":[ + "main" + ], + "acl":{ + "read":true + } + }, + { + "module":"content_type", + "content_types":[ + "$all" + ], + "acl":{ + "read":true, + "sub_acl":{ + "read":true + } + } + }, + { + "module":"asset", + "assets":[ + "$all" + ], + "acl":{ + "read":true, + "update":true, + "publish":true, + "delete":true + } + }, + { + "module":"folder", + "folders":[ + "$all" + ], + "acl":{ + "read":true, + "update":true, + "publish":true, + "delete":true, + "sub_acl":{ + "read":true, + "update":true, + "publish":true, + "delete":true + } + } + }, + { + "module":"environment", + "environments":[ + "$all" + ], + "acl":{ + "read":true + } + }, + { + "module":"locale", + "locales":[ + "$all" + ], + "acl":{ + "read":true + } + } + ], + "uid":"blt668fa7872710da7c" + } + } \ No newline at end of file diff --git a/src/test/resources/mocktaxonomy/create.json b/src/test/resources/mocktaxonomy/create.json index 9e0c2a8e..d452e367 100644 --- a/src/test/resources/mocktaxonomy/create.json +++ b/src/test/resources/mocktaxonomy/create.json @@ -1,8 +1,8 @@ { "taxonomy": { - "uid": "sample_one", - "name": "Sample One", + "uid": "sample_two", + "name": "Sample Two", "description": "Description for the sample one taxonomy." } } \ No newline at end of file diff --git a/src/test/resources/mocktaxonomy/update.json b/src/test/resources/mocktaxonomy/update.json index ece28e56..99f965db 100644 --- a/src/test/resources/mocktaxonomy/update.json +++ b/src/test/resources/mocktaxonomy/update.json @@ -1,6 +1,6 @@ { "taxonomy": { - "name": "Updated Sample One", + "name": "Updated Sample Two", "description": "Updated description for the sample one taxonomy." } } \ No newline at end of file diff --git a/testng.xml b/testng.xml deleted file mode 100644 index 23abbf08..00000000 --- a/testng.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file