diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e5196af32..2529e47ca 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,4 +1,3 @@ - # Please see the documentation for all configuration options: # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates diff --git a/.github/labeler.yml b/.github/labeler.yml index 8aa9ae470..7dccf8144 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,13 +1,13 @@ tests: -- src/test/**/* + - src/test/**/* java: -- '**/*.java' + - '**/*.java' documentation: -- '**/*.md' + - '**/*.md' markdown: -- '**/*.md' + - '**/*.md' github-actions: -- .github/**/* + - .github/**/* dependencies: -- pom.xml + - pom.xml diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d63003915..0be5e3381 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -38,46 +38,46 @@ jobs: # Learn more about CodeQL language support at https://git.io/codeql-language-support steps: - - name: Checkout repository - uses: actions/checkout@v3 - + - name: Checkout repository + uses: actions/checkout@v3 - - uses: actions/checkout@v3 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: '17' - distribution: 'temurin' - + - uses: actions/checkout@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main - # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 - #- run: | - # make bootstrap - # make release + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{matrix.language}}" + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml index b74c97588..541b27131 100644 --- a/.github/workflows/greetings.yml +++ b/.github/workflows/greetings.yml @@ -1,6 +1,6 @@ name: Greetings -on: [pull_request_target, issues] +on: [ pull_request_target, issues ] jobs: greeting: @@ -9,8 +9,8 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/first-interaction@v1 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - issue-message: "Hello and welcome! We're glad to see that you've opened your first issue. We appreciate your contribution and would love to hear more about the problem you're experiencing. Our team is actively monitoring this repository and we will do our best to respond to your issue as soon as possible. Thank you for using our project and we look forward to working with you!" - pr-message: "Hello and welcome! We are excited to see your first pull request and appreciate your contribution to our project. Our team is reviewing your changes and we will provide feedback as soon as possible. Thank you for taking the time to improve our project and we look forward to working with you!" + - uses: actions/first-interaction@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + issue-message: "Hello and welcome! We're glad to see that you've opened your first issue. We appreciate your contribution and would love to hear more about the problem you're experiencing. Our team is actively monitoring this repository and we will do our best to respond to your issue as soon as possible. Thank you for using our project and we look forward to working with you!" + pr-message: "Hello and welcome! We are excited to see your first pull request and appreciate your contribution to our project. Our team is reviewing your changes and we will provide feedback as soon as possible. Thank you for taking the time to improve our project and we look forward to working with you!" diff --git a/.github/workflows/javadoc.yml b/.github/workflows/javadoc.yml index ee560f81c..655a7fe85 100644 --- a/.github/workflows/javadoc.yml +++ b/.github/workflows/javadoc.yml @@ -22,7 +22,7 @@ jobs: ref: javadoc persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token. fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. - - name: merge changes + - name: merge changes run: | git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml index 461356907..ad476f722 100644 --- a/.github/workflows/label.yml +++ b/.github/workflows/label.yml @@ -6,7 +6,7 @@ # https://github.com/actions/labeler name: Labeler -on: [pull_request_target] +on: [ pull_request_target ] jobs: label: @@ -17,6 +17,6 @@ jobs: pull-requests: write steps: - - uses: actions/labeler@v4 - with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" + - uses: actions/labeler@v4 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml index 3a24d58fc..7ecbc021f 100644 --- a/.github/workflows/maven-ci.yml +++ b/.github/workflows/maven-ci.yml @@ -15,15 +15,15 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: '17' - distribution: 'temurin' - cache: maven - - name: Build with Maven - run: mvn -B package --file pom.xml - #coverage - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v3 + - uses: actions/checkout@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn -B package --file pom.xml + #coverage + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3 diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index 9ff415f7c..7d4ec9cd2 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -5,8 +5,8 @@ name: Maven Package on: release: - types: [created] - + types: [ created ] + workflow_dispatch: jobs: diff --git a/.gitignore b/.gitignore index 9524166bb..c8df4d858 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ hs_err_pid* /target/ /src/test/java/com/whatsapp/api/TestConstants.java /src/test/java/com/whatsapp/api/TestConstants.java +/htmlReport +/machinet.conf diff --git a/src/main/java/com/whatsapp/api/domain/messages/Header.java b/src/main/java/com/whatsapp/api/domain/messages/Header.java index e28f6d623..cd5a63491 100644 --- a/src/main/java/com/whatsapp/api/domain/messages/Header.java +++ b/src/main/java/com/whatsapp/api/domain/messages/Header.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.whatsapp.api.domain.messages.type.HeaderType; -//TODO: Header is incomplete + /** *

Header content displayed on top of a message. You cannot set a header if your interactive object is of product type

*/ @@ -14,17 +14,55 @@ public class Header { * The Type. */ @JsonProperty("type") - public HeaderType type; + private HeaderType type; /** * The Text. */ @JsonProperty("text") - public String text; + private String text; + + /** + * Required if type is set to document. + * Contains the media object for this document. + */ + @JsonProperty("document") + private Document document; + + /** + * Required if type is set to image. + * Contains the media object for this image. + */ + @JsonProperty("image") + private Image image; + + /** + * Required if type is set to video. + * Contains the media object for this video. + */ + @JsonProperty("video") + private Video video; + + + /** + * Instantiates a new Header. + * + * @param type Allways Required. The header type you would like to use + */ + public Header(HeaderType type) { + this.type = type; + } + + + /** + * Instantiates a new Header. + */ + public Header() { + } /** * Gets type. * - * @return the type + * @return the Header */ public HeaderType getType() { return type; @@ -33,8 +71,8 @@ public HeaderType getType() { /** * Sets type. * - * @param type the type - * @return the type + * @param type Required. The header type you would like to us + * @return the Header */ public Header setType(HeaderType type) { this.type = type; @@ -44,7 +82,7 @@ public Header setType(HeaderType type) { /** * Gets text. * - * @return the text + * @return the Header */ public String getText() { return text; @@ -53,11 +91,76 @@ public String getText() { /** * Sets text. * - * @param text the text - * @return the text + * @param text Required if type is set to text. Text for the header. + *
Formatting allows emojis, but not markdown. + *
Maximum length is 60 characters. + * @return the Header */ public Header setText(String text) { this.text = text; return this; } + + /** + * Gets document. + * + * @return the Header + */ + public Document getDocument() { + return document; + } + + /** + * Sets document. + * + * @param document Required if type is set to document. + *
Contains the media object for this document. + * @return the Header + */ + public Header setDocument(Document document) { + this.document = document; + return this; + } + + /** + * Gets image. + * + * @return the Header + */ + public Image getImage() { + return image; + } + + /** + * Sets image. + * + * @param image Required if type is set to image. + *
Contains the media object for this image. + * @return the Header + */ + public Header setImage(Image image) { + this.image = image; + return this; + } + + /** + * Gets video. + * + * @return the Header + */ + public Video getVideo() { + return video; + } + + /** + * Sets video. + * + * @param video Required if type is set to video. + *
Contains the media object for this video. + * @return the Header + */ + public Header setVideo(Video video) { + this.video = video; + return this; + } } diff --git a/src/main/java/com/whatsapp/api/domain/messages/LocationMessage.java b/src/main/java/com/whatsapp/api/domain/messages/LocationMessage.java index 24141eb24..c36daa10b 100644 --- a/src/main/java/com/whatsapp/api/domain/messages/LocationMessage.java +++ b/src/main/java/com/whatsapp/api/domain/messages/LocationMessage.java @@ -41,58 +41,61 @@ public LocationMessage setName(String name) { /** * Gets longitude. + * * @return the longitude */ - public String getLongitude() { - return longitude; - } + public String getLongitude() { + return longitude; + } - /** - * Sets longitude. - * - * @param longitude - * @return LocationMessage - */ - public LocationMessage setLongitude(String longitude) { - this.longitude = longitude; - return this; - } + /** + * Sets longitude. + * + * @param longitude + * @return LocationMessage + */ + public LocationMessage setLongitude(String longitude) { + this.longitude = longitude; + return this; + } - /** - * Gets latitude. - * @return the latitude - */ - public String getLatitude() { - return latitude; - } + /** + * Gets latitude. + * + * @return the latitude + */ + public String getLatitude() { + return latitude; + } - /** - * Sets latitude. - * - * @param latitude - * @return LocationMessage - */ - public LocationMessage setLatitude(String latitude) { - this.latitude = latitude; - return this; - } + /** + * Sets latitude. + * + * @param latitude + * @return LocationMessage + */ + public LocationMessage setLatitude(String latitude) { + this.latitude = latitude; + return this; + } - /** - * Gets address. - * @return the address - */ - public String getAddress() { - return address; - } + /** + * Gets address. + * + * @return the address + */ + public String getAddress() { + return address; + } - /** - * Sets address. - * - * @param address - * @return LocationMessage - */ - public LocationMessage setAddress(String address) { - this.address = address; - return this; - } + /** + * Sets address. + * + * @param address + * @return LocationMessage + */ + public LocationMessage setAddress(String address) { + this.address = address; + return this; + } } \ No newline at end of file diff --git a/src/test/java/com/whatsapp/api/examples/SendInteractiveMessageExample.java b/src/test/java/com/whatsapp/api/examples/SendInteractiveMessageExample.java index c746e38db..c863adb3f 100644 --- a/src/test/java/com/whatsapp/api/examples/SendInteractiveMessageExample.java +++ b/src/test/java/com/whatsapp/api/examples/SendInteractiveMessageExample.java @@ -7,14 +7,17 @@ import com.whatsapp.api.domain.messages.Action; import com.whatsapp.api.domain.messages.Body; import com.whatsapp.api.domain.messages.Button; +import com.whatsapp.api.domain.messages.Document; import com.whatsapp.api.domain.messages.Footer; import com.whatsapp.api.domain.messages.Header; +import com.whatsapp.api.domain.messages.Image; import com.whatsapp.api.domain.messages.InteractiveMessage; import com.whatsapp.api.domain.messages.Message.MessageBuilder; import com.whatsapp.api.domain.messages.Product; import com.whatsapp.api.domain.messages.Reply; import com.whatsapp.api.domain.messages.Row; import com.whatsapp.api.domain.messages.Section; +import com.whatsapp.api.domain.messages.Video; import com.whatsapp.api.domain.messages.response.MessageResponse; import com.whatsapp.api.domain.messages.type.ButtonType; import com.whatsapp.api.domain.messages.type.HeaderType; @@ -41,6 +44,13 @@ public static void main(String[] args) throws JsonProcessingException { listMessage(whatsappBusinessCloudApi); + withImageHeader(whatsappBusinessCloudApi); + + withVideoHeader(whatsappBusinessCloudApi); + + withDocumentHeader(whatsappBusinessCloudApi); + + } private static void multiProductMessage(WhatsappBusinessCloudApi whatsappBusinessCloudApi) { @@ -127,6 +137,93 @@ private static void buttonMessage(WhatsappBusinessCloudApi whatsappBusinessCloud System.out.println(messageResponse); } + private static void withImageHeader(WhatsappBusinessCloudApi whatsappBusinessCloudApi) throws JsonProcessingException { + var message = MessageBuilder.builder()// + .setTo(PHONE_NUMBER_1)// + .buildInteractiveMessage(InteractiveMessage.build() // + .setAction(new Action() // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278454") // + .setTitle("YES"))) // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278455") // + .setTitle("NO"))) // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278456") // + .setTitle("CHANGE")))) // + .setType(InteractiveMessageType.BUTTON) // + .setHeader(new Header()// + .setType(HeaderType.IMAGE)// + .setImage(new Image().setLink("https://upload.wikimedia.org/wikipedia/commons/8/87/Tamarama_Beach.jpg"))).setBody(new Body() // + .setText("Would you like to confirm your appointment for tomorrow?")) // + .setFooter(new Footer().setText("Choose an option:"))); + System.out.println(new ObjectMapper().writeValueAsString(message)); + + MessageResponse messageResponse = whatsappBusinessCloudApi.sendMessage(PHONE_NUMBER_ID, message); + + System.out.println(messageResponse); + } + + private static void withDocumentHeader(WhatsappBusinessCloudApi whatsappBusinessCloudApi) throws JsonProcessingException { + var message = MessageBuilder.builder()// + .setTo(PHONE_NUMBER_1)// + .buildInteractiveMessage(InteractiveMessage.build() // + .setAction(new Action() // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278454") // + .setTitle("YES"))) // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278455") // + .setTitle("NO"))) // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278456") // + .setTitle("CHANGE")))) // + .setType(InteractiveMessageType.BUTTON) // + .setHeader(new Header()// + .setType(HeaderType.DOCUMENT)// + .setDocument(new Document().setFileName("schedule.pdf").setLink("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"))).setBody(new Body() // + .setText("Would you like to confirm your appointment for tomorrow?")) // + .setFooter(new Footer().setText("Choose an option:"))); + System.out.println(new ObjectMapper().writeValueAsString(message)); + + MessageResponse messageResponse = whatsappBusinessCloudApi.sendMessage(PHONE_NUMBER_ID, message); + + System.out.println(messageResponse); + } + + private static void withVideoHeader(WhatsappBusinessCloudApi whatsappBusinessCloudApi) throws JsonProcessingException { + var message = MessageBuilder.builder()// + .setTo(PHONE_NUMBER_1)// + .buildInteractiveMessage(InteractiveMessage.build() // + .setAction(new Action() // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278454") // + .setTitle("YES"))) // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278455") // + .setTitle("NO"))) // + ) // + .setType(InteractiveMessageType.BUTTON) // + .setHeader(new Header()// + .setType(HeaderType.VIDEO)// + .setVideo(new Video().setLink("https://joy1.videvo.net/videvo_files/video/free/2014-04/large_watermarked/Lonely_tree_at_Sunset_slow_motion_CCBY_NatureClip_preview.mp4"))).setBody(new Body() // + .setText("Do you like this video?")) // + .setFooter(new Footer().setText("Choose an option:"))); + System.out.println(new ObjectMapper().writeValueAsString(message)); + + MessageResponse messageResponse = whatsappBusinessCloudApi.sendMessage(PHONE_NUMBER_ID, message); + + System.out.println(messageResponse); + } + private static void listMessage(WhatsappBusinessCloudApi whatsappBusinessCloudApi) throws JsonProcessingException { var message = MessageBuilder.builder()// .setTo(PHONE_NUMBER_1)// diff --git a/src/test/java/com/whatsapp/api/examples/SendLocationMessageExample.java b/src/test/java/com/whatsapp/api/examples/SendLocationMessageExample.java index e3eb2418b..c2aae8dd5 100644 --- a/src/test/java/com/whatsapp/api/examples/SendLocationMessageExample.java +++ b/src/test/java/com/whatsapp/api/examples/SendLocationMessageExample.java @@ -1,20 +1,20 @@ package com.whatsapp.api.examples; -import static com.whatsapp.api.TestConstants.PHONE_NUMBER_1; -import static com.whatsapp.api.TestConstants.PHONE_NUMBER_ID; -import static com.whatsapp.api.TestConstants.TOKEN; - import com.whatsapp.api.WhatsappApiFactory; import com.whatsapp.api.domain.messages.LocationMessage; import com.whatsapp.api.domain.messages.Message.MessageBuilder; import com.whatsapp.api.domain.messages.response.MessageResponse; import com.whatsapp.api.impl.WhatsappBusinessCloudApi; +import static com.whatsapp.api.TestConstants.PHONE_NUMBER_1; +import static com.whatsapp.api.TestConstants.PHONE_NUMBER_ID; +import static com.whatsapp.api.TestConstants.TOKEN; + public class SendLocationMessageExample { - public static void main(String[] args) { - - WhatsappApiFactory factory = WhatsappApiFactory.newInstance(TOKEN); + public static void main(String[] args) { + + WhatsappApiFactory factory = WhatsappApiFactory.newInstance(TOKEN); WhatsappBusinessCloudApi whatsappBusinessCloudApi = factory.newBusinessCloudApi(); var locationMessage = new LocationMessage()// @@ -29,6 +29,6 @@ public static void main(String[] args) { System.out.println(messageResponse); - } + } } diff --git a/src/test/java/com/whatsapp/api/impl/WhatsappBusinessCloudApiTest.java b/src/test/java/com/whatsapp/api/impl/WhatsappBusinessCloudApiTest.java index 61cb400a5..5c86fe5e5 100644 --- a/src/test/java/com/whatsapp/api/impl/WhatsappBusinessCloudApiTest.java +++ b/src/test/java/com/whatsapp/api/impl/WhatsappBusinessCloudApiTest.java @@ -763,6 +763,132 @@ void testSendInteractiveMessageWithButtons() throws InterruptedException, JSONEx } + @Test + void testSendInteractiveMessageWithImageHeader() throws InterruptedException, JSONException, IOException, URISyntaxException { + mockWebServer.enqueue(new MockResponse().setResponseCode(200).setBody(DEFAULT_SEND_MESSAGE_RESPONSE)); + + var expectedJson = fromResource(EXPECTED_FOLDER + "expectedMessage14.json"); + + var interactive = InteractiveMessage.build() // + .setAction(new Action() // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278454") // + .setTitle("YES"))) // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278455") // + .setTitle("NO"))) // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278456") // + .setTitle("CHANGE")))) // + .setType(InteractiveMessageType.BUTTON) // + .setHeader(new Header()// + .setType(HeaderType.IMAGE)// + .setImage(new Image().setLink("https://upload.wikimedia.org/wikipedia/commons/8/87/Tamarama_Beach.jpg"))// + ).setBody(new Body() // + .setText("Would you like to confirm your appointment for tomorrow?")) // + .setFooter(new Footer().setText("Choose an option:")); + + var message = MessageBuilder.builder()// + .setTo(PHONE_NUMBER_1)// + .buildInteractiveMessage(interactive); + + + var response = whatsappBusinessCloudApi.sendMessage(PHONE_NUMBER_ID, message); + Assertions.assertNotNull(response); + RecordedRequest recordedRequest = mockWebServer.takeRequest(); + Assertions.assertEquals("POST", recordedRequest.getMethod()); + Assertions.assertEquals("/" + API_VERSION + "/" + PHONE_NUMBER_ID + "/messages", recordedRequest.getPath()); + // System.out.println(recordedRequest.getBody().readUtf8()); + JSONAssert.assertEquals(expectedJson, recordedRequest.getBody().readUtf8(), JSONCompareMode.STRICT); + + } + + @Test + void testSendInteractiveMessageWithVideoHeader() throws InterruptedException, JSONException, IOException, URISyntaxException { + mockWebServer.enqueue(new MockResponse().setResponseCode(200).setBody(DEFAULT_SEND_MESSAGE_RESPONSE)); + + var expectedJson = fromResource(EXPECTED_FOLDER + "expectedMessage15.json"); + + var interactive = InteractiveMessage.build() // + .setAction(new Action() // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278454") // + .setTitle("YES"))) // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278455") // + .setTitle("NO"))) // + ) // + .setType(InteractiveMessageType.BUTTON) // + .setHeader(new Header()// + .setType(HeaderType.VIDEO)// + .setVideo(new Video().setLink("https://joy1.videvo.net/videvo_files/video/free/2014-04/large_watermarked/Lonely_tree_at_Sunset_slow_motion_CCBY_NatureClip_preview.mp4"))).setBody(new Body() // + .setText("Do you like this video?")) // + .setFooter(new Footer().setText("Choose an option:")); + + var message = MessageBuilder.builder()// + .setTo(PHONE_NUMBER_1)// + .buildInteractiveMessage(interactive); + + + var response = whatsappBusinessCloudApi.sendMessage(PHONE_NUMBER_ID, message); + Assertions.assertNotNull(response); + RecordedRequest recordedRequest = mockWebServer.takeRequest(); + Assertions.assertEquals("POST", recordedRequest.getMethod()); + Assertions.assertEquals("/" + API_VERSION + "/" + PHONE_NUMBER_ID + "/messages", recordedRequest.getPath()); + //System.out.println(recordedRequest.getBody().readUtf8()); + JSONAssert.assertEquals(expectedJson, recordedRequest.getBody().readUtf8(), JSONCompareMode.STRICT); + + } + + @Test + void testSendInteractiveMessageWithDocumentHeader() throws InterruptedException, JSONException, IOException, URISyntaxException { + mockWebServer.enqueue(new MockResponse().setResponseCode(200).setBody(DEFAULT_SEND_MESSAGE_RESPONSE)); + + var expectedJson = fromResource(EXPECTED_FOLDER + "expectedMessage16.json"); + + var interactive = InteractiveMessage.build() // + .setAction(new Action() // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278454") // + .setTitle("YES"))) // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278455") // + .setTitle("NO"))) // + .addButton(new Button() // + .setType(ButtonType.REPLY).setReply(new Reply() // + .setId("1278456") // + .setTitle("CHANGE")))) // + .setType(InteractiveMessageType.BUTTON) // + .setHeader(new Header()// + .setType(HeaderType.DOCUMENT)// + .setDocument(new Document()// + .setFileName("schedule.pdf").setLink("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf")))// + .setBody(new Body() // + .setText("Would you like to confirm your appointment for tomorrow?")) // + .setFooter(new Footer().setText("Choose an option:")); + + var message = MessageBuilder.builder()// + .setTo(PHONE_NUMBER_1)// + .buildInteractiveMessage(interactive); + + + var response = whatsappBusinessCloudApi.sendMessage(PHONE_NUMBER_ID, message); + Assertions.assertNotNull(response); + RecordedRequest recordedRequest = mockWebServer.takeRequest(); + Assertions.assertEquals("POST", recordedRequest.getMethod()); + Assertions.assertEquals("/" + API_VERSION + "/" + PHONE_NUMBER_ID + "/messages", recordedRequest.getPath()); + //System.out.println(recordedRequest.getBody().readUtf8()); + JSONAssert.assertEquals(expectedJson, recordedRequest.getBody().readUtf8(), JSONCompareMode.STRICT); + + } + @Test void testSendInteractiveMessageWithList() throws InterruptedException, JSONException, IOException, URISyntaxException { mockWebServer.enqueue(new MockResponse().setResponseCode(200).setBody(DEFAULT_SEND_MESSAGE_RESPONSE)); @@ -980,9 +1106,9 @@ void testLocationMessage() throws IOException, URISyntaxException, InterruptedEx var message = MessageBuilder.builder()// .setTo(PHONE_NUMBER_1)// .buildLocationMessage(new LocationMessage()// - .setLatitude("39.284064") - .setLongitude("-84.265742") - .setName("Loveland Castle Museum") + .setLatitude("39.284064")// + .setLongitude("-84.265742")// + .setName("Loveland Castle Museum")// .setAddress("12025 Shore Dr, Loveland, OH 45140")); diff --git a/src/test/java/com/whatsapp/api/impl/WhatsappBusinessManagementApiTest.java b/src/test/java/com/whatsapp/api/impl/WhatsappBusinessManagementApiTest.java index 59bf811b5..bff98676b 100644 --- a/src/test/java/com/whatsapp/api/impl/WhatsappBusinessManagementApiTest.java +++ b/src/test/java/com/whatsapp/api/impl/WhatsappBusinessManagementApiTest.java @@ -454,7 +454,7 @@ void testRetrieveMessageTemplate1() throws IOException, URISyntaxException, JSON //TODO: review button var returnedJson = new ObjectMapper().writeValueAsString(templates); - JSONAssert.assertEquals(expectedJson, returnedJson,JSONCompareMode.STRICT); + JSONAssert.assertEquals(expectedJson, returnedJson, JSONCompareMode.STRICT); // data[1].components[3].buttons[0] Assertions.assertEquals(7, templates.data().size()); @@ -462,9 +462,9 @@ void testRetrieveMessageTemplate1() throws IOException, URISyntaxException, JSON Assertions.assertEquals("Hello {{1}}, welcome to our {{2}} test.", templates.data().get(0).components().get(1).getText()); Assertions.assertEquals("1772832833109192", templates.data().get(6).id()); - var buttonComponent = (ButtonComponent) templates.data().get(1).components().get(3); + var buttonComponent = (ButtonComponent) templates.data().get(1).components().get(3); - Assertions.assertEquals(ButtonType.QUICK_REPLY,buttonComponent.getButtons().get(0).getType()); + Assertions.assertEquals(ButtonType.QUICK_REPLY, buttonComponent.getButtons().get(0).getType()); } diff --git a/src/test/resources/expected/message/expectedMessage14.json b/src/test/resources/expected/message/expectedMessage14.json new file mode 100644 index 000000000..51e97d9a4 --- /dev/null +++ b/src/test/resources/expected/message/expectedMessage14.json @@ -0,0 +1,46 @@ +{ + "messaging_product": "whatsapp", + "recipient_type": "individual", + "interactive": { + "action": { + "buttons": [ + { + "type": "reply", + "reply": { + "id": "1278454", + "title": "YES" + } + }, + { + "type": "reply", + "reply": { + "id": "1278455", + "title": "NO" + } + }, + { + "type": "reply", + "reply": { + "id": "1278456", + "title": "CHANGE" + } + } + ] + }, + "type": "BUTTON", + "header": { + "type": "image", + "image": { + "link": "https://upload.wikimedia.org/wikipedia/commons/8/87/Tamarama_Beach.jpg" + } + }, + "body": { + "text": "Would you like to confirm your appointment for tomorrow?" + }, + "footer": { + "text": "Choose an option:" + } + }, + "to": "121212121212", + "type": "interactive" +} \ No newline at end of file diff --git a/src/test/resources/expected/message/expectedMessage15.json b/src/test/resources/expected/message/expectedMessage15.json new file mode 100644 index 000000000..e2a9dcaaa --- /dev/null +++ b/src/test/resources/expected/message/expectedMessage15.json @@ -0,0 +1,39 @@ +{ + "messaging_product": "whatsapp", + "recipient_type": "individual", + "interactive": { + "action": { + "buttons": [ + { + "type": "reply", + "reply": { + "id": "1278454", + "title": "YES" + } + }, + { + "type": "reply", + "reply": { + "id": "1278455", + "title": "NO" + } + } + ] + }, + "type": "BUTTON", + "header": { + "type": "video", + "video": { + "link": "https://joy1.videvo.net/videvo_files/video/free/2014-04/large_watermarked/Lonely_tree_at_Sunset_slow_motion_CCBY_NatureClip_preview.mp4" + } + }, + "body": { + "text": "Do you like this video?" + }, + "footer": { + "text": "Choose an option:" + } + }, + "to": "121212121212", + "type": "interactive" +} \ No newline at end of file diff --git a/src/test/resources/expected/message/expectedMessage16.json b/src/test/resources/expected/message/expectedMessage16.json new file mode 100644 index 000000000..ea7003762 --- /dev/null +++ b/src/test/resources/expected/message/expectedMessage16.json @@ -0,0 +1,47 @@ +{ + "messaging_product": "whatsapp", + "recipient_type": "individual", + "interactive": { + "action": { + "buttons": [ + { + "type": "reply", + "reply": { + "id": "1278454", + "title": "YES" + } + }, + { + "type": "reply", + "reply": { + "id": "1278455", + "title": "NO" + } + }, + { + "type": "reply", + "reply": { + "id": "1278456", + "title": "CHANGE" + } + } + ] + }, + "type": "BUTTON", + "header": { + "type": "document", + "document": { + "link": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf", + "filename": "schedule.pdf" + } + }, + "body": { + "text": "Would you like to confirm your appointment for tomorrow?" + }, + "footer": { + "text": "Choose an option:" + } + }, + "to": "121212121212", + "type": "interactive" +} \ No newline at end of file