View Javadoc
1   /**
2    * Copyright (c) 2013-2023, jcabi.com
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met: 1) Redistributions of source code must retain the above
8    * copyright notice, this list of conditions and the following
9    * disclaimer. 2) Redistributions in binary form must reproduce the above
10   * copyright notice, this list of conditions and the following
11   * disclaimer in the documentation and/or other materials provided
12   * with the distribution. 3) Neither the name of the jcabi.com nor
13   * the names of its contributors may be used to endorse or promote
14   * products derived from this software without specific prior written
15   * permission.
16   *
17   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21   * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28   * OF THE POSSIBILITY OF SUCH DAMAGE.
29   */
30  package com.jcabi.github;
31  
32  import com.jcabi.aspects.Tv;
33  import com.jcabi.github.mock.MkGithub;
34  import com.jcabi.http.Request;
35  import com.jcabi.http.mock.MkAnswer;
36  import com.jcabi.http.mock.MkContainer;
37  import com.jcabi.http.mock.MkGrizzlyContainer;
38  import com.jcabi.http.mock.MkQuery;
39  import com.jcabi.http.request.ApacheRequest;
40  import com.jcabi.http.request.FakeRequest;
41  import com.jcabi.http.request.JdkRequest;
42  import java.net.HttpURLConnection;
43  import java.util.Collections;
44  import javax.json.Json;
45  import javax.json.JsonObject;
46  import org.hamcrest.MatcherAssert;
47  import org.hamcrest.Matchers;
48  import org.junit.Rule;
49  import org.junit.Test;
50  import org.mockito.Mockito;
51  
52  /**
53   * Test case for {@link RtPullComments}.
54   *
55   * @author Carlos Miranda (miranda.cma@gmail.com)
56   * @version $Id: 8e58aa69425289d01ca8e9f1a3a617655cb56cc1 $
57   * @checkstyle ClassDataAbstractionCoupling (500 lines)
58   */
59  @SuppressWarnings("PMD.TooManyMethods")
60  public final class RtPullCommentsTest {
61  
62      /**
63       * The rule for skipping test if there's BindException.
64       * @checkstyle VisibilityModifierCheck (3 lines)
65       */
66      @Rule
67      public final transient RandomPort resource = new RandomPort();
68  
69      /**
70       * RtPullComments can fetch a single comment.
71       *
72       * @throws Exception If something goes wrong.
73       */
74      @Test
75      public void fetchesPullComment() throws Exception {
76          final Pull pull = Mockito.mock(Pull.class);
77          Mockito.doReturn(repo()).when(pull).repo();
78          final RtPullComments comments =
79              new RtPullComments(new FakeRequest(), pull);
80          MatcherAssert.assertThat(
81              comments.get(1),
82              Matchers.notNullValue()
83          );
84      }
85  
86      /**
87       * RtPullComments can fetch all pull comments for a repo.
88       *
89       * @throws Exception If something goes wrong.
90       */
91      @Test
92      public void iteratesRepoPullComments() throws Exception {
93          final Pull pull = Mockito.mock(Pull.class);
94          Mockito.doReturn(repo()).when(pull).repo();
95          try (
96              final MkContainer container = new MkGrizzlyContainer().next(
97                  new MkAnswer.Simple(
98                      HttpURLConnection.HTTP_OK,
99                      Json.createArrayBuilder()
100                         .add(comment("comment 1"))
101                         .add(comment("comment 2"))
102                         .build().toString()
103                 )
104             ).start(this.resource.port())
105         ) {
106             final RtPullComments comments = new RtPullComments(
107                 new JdkRequest(container.home()), pull
108             );
109             MatcherAssert.assertThat(
110                 comments.iterate(Collections.<String, String>emptyMap()),
111                 Matchers.<PullComment>iterableWithSize(2)
112             );
113             container.stop();
114         }
115     }
116 
117     /**
118      * RtPullComments can fetch pull comments for a pull request.
119      *
120      * @throws Exception If something goes wrong.
121      */
122     @Test
123     public void iteratesPullRequestComments() throws Exception {
124         final Pull pull = Mockito.mock(Pull.class);
125         Mockito.doReturn(repo()).when(pull).repo();
126         try (
127             final MkContainer container = new MkGrizzlyContainer().next(
128                 new MkAnswer.Simple(
129                     HttpURLConnection.HTTP_OK,
130                     Json.createArrayBuilder()
131                         .add(comment("comment 3"))
132                         .add(comment("comment 4"))
133                         .build().toString()
134                 )
135             ).start(this.resource.port())
136         ) {
137             final RtPullComments comments = new RtPullComments(
138                 new JdkRequest(container.home()), pull
139             );
140             MatcherAssert.assertThat(
141                 comments.iterate(1, Collections.<String, String>emptyMap()),
142                 Matchers.<PullComment>iterableWithSize(2)
143             );
144             container.stop();
145         }
146     }
147 
148     /**
149      * RtPullComments can post a new a pull comment.
150      *
151      * @throws Exception If something goes wrong.
152      */
153     @Test
154     public void createsPullComment() throws Exception {
155         // @checkstyle MultipleStringLiterals (3 line)
156         final String body = "test-body";
157         final String commit = "test-commit-id";
158         final String path = "test-path";
159         final int position = 4;
160         final String response = pulls(body, commit, path, position).toString();
161         try (
162             final MkContainer container = new MkGrizzlyContainer().next(
163                 new MkAnswer.Simple(HttpURLConnection.HTTP_CREATED, response)
164             ).next(new MkAnswer.Simple(HttpURLConnection.HTTP_OK, response))
165                 .start(this.resource.port())
166         ) {
167             final Pull pull = Mockito.mock(Pull.class);
168             Mockito.doReturn(repo()).when(pull).repo();
169             final RtPullComments pullComments = new RtPullComments(
170                 new ApacheRequest(container.home()),
171                     pull
172             );
173             final PullComment pullComment = pullComments.post(
174                 body, commit, path, position
175             );
176             MatcherAssert.assertThat(
177                 container.take().method(),
178                 Matchers.equalTo(Request.POST)
179             );
180             MatcherAssert.assertThat(
181                 new PullComment.Smart(pullComment).commitId(),
182                 Matchers.equalTo(commit)
183             );
184             container.stop();
185         }
186     }
187 
188     /**
189      * RtPullComments can reply to an existing pull comment.
190      *
191      * @throws Exception If something goes wrong.
192      */
193     @Test
194     public void createsPullCommentReply() throws Exception {
195         final String body = "test-body";
196         final int number = 4;
197         final String response = Json.createObjectBuilder()
198             // @checkstyle MultipleStringLiterals (2 line)
199             .add("id", Tv.BILLION)
200             .add("body", body)
201             .add("in_reply_to", number)
202             .build()
203             .toString();
204         try (
205             final MkContainer container = new MkGrizzlyContainer().next(
206                 new MkAnswer.Simple(HttpURLConnection.HTTP_CREATED, response)
207             ).next(new MkAnswer.Simple(HttpURLConnection.HTTP_OK, response))
208                 .start(this.resource.port())
209         ) {
210             final Pull pull = Mockito.mock(Pull.class);
211             Mockito.doReturn(repo()).when(pull).repo();
212             final RtPullComments pullComments = new RtPullComments(
213                 new ApacheRequest(container.home()),
214                     pull
215             );
216             final PullComment pullComment = pullComments.reply(
217                 body, number
218             );
219             MatcherAssert.assertThat(
220                 container.take().method(),
221                 Matchers.equalTo(Request.POST)
222             );
223             MatcherAssert.assertThat(
224                 new PullComment.Smart(pullComment).reply(),
225                 Matchers.equalTo(number)
226             );
227             container.stop();
228         }
229     }
230 
231     /**
232      * RtPullComments can remove a pull comment.
233      *
234      * @throws Exception If something goes wrong.
235      */
236     @Test
237     public void removesPullComment() throws Exception {
238         try (
239             final MkContainer container = new MkGrizzlyContainer().next(
240                 new MkAnswer.Simple(HttpURLConnection.HTTP_NO_CONTENT, "")
241             ).start(this.resource.port())
242         ) {
243             final Pull pull = Mockito.mock(Pull.class);
244             final Repo repository = repo();
245             Mockito.doReturn(repository).when(pull).repo();
246             final RtPullComments comments =
247                 new RtPullComments(new ApacheRequest(container.home()), pull);
248             comments.remove(2);
249             final MkQuery query = container.take();
250             MatcherAssert.assertThat(
251                 query.method(), Matchers.equalTo(Request.DELETE)
252             );
253             MatcherAssert.assertThat(
254                 query.uri().toString(),
255                 Matchers.endsWith(
256                     String.format(
257                         "/repos/johnny/%s/pulls/0/comments/2",
258                         repository.coordinates().repo()
259                     )
260                 )
261             );
262             container.stop();
263         }
264     }
265 
266     /**
267      * This method returns a Repo for testing.
268      * @return Repo - a repo to be used for test.
269      * @throws Exception - if anything goes wrong.
270      */
271     private static Repo repo() throws Exception {
272         return new MkGithub("johnny").randomRepo();
273     }
274 
275     /**
276      * Create and return JsonObject to test.
277      * @param body The body
278      * @param commit Commit
279      * @param path Path
280      * @param position Position
281      * @return JsonObject
282      * @checkstyle ParameterNumberCheck (10 lines)
283      */
284     private static JsonObject pulls(final String body, final String commit,
285         final String path, final int position) {
286         return Json.createObjectBuilder()
287             // @checkstyle MultipleStringLiterals (2 line)
288             .add("id", Tv.BILLION)
289             .add("body", body)
290             .add("commit_id", commit)
291             .add("path", path)
292             .add("position", position)
293             .build();
294     }
295 
296     /**
297      * Create and return JsonObject to test.
298      * @param bodytext Body of the comment
299      * @return JsonObject
300      */
301     private static JsonObject comment(final String bodytext) {
302         return Json.createObjectBuilder()
303             // @checkstyle MultipleStringLiterals (2 line)
304             .add("id", 1)
305             .add("body", bodytext)
306             .build();
307     }
308 
309 }