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.Immutable;
33  import com.jcabi.http.Request;
34  import com.jcabi.http.mock.MkAnswer;
35  import com.jcabi.http.mock.MkContainer;
36  import com.jcabi.http.mock.MkGrizzlyContainer;
37  import com.jcabi.http.mock.MkQuery;
38  import com.jcabi.http.request.ApacheRequest;
39  import java.net.HttpURLConnection;
40  import javax.json.Json;
41  import javax.json.JsonArray;
42  import javax.json.JsonObject;
43  import org.hamcrest.MatcherAssert;
44  import org.hamcrest.Matchers;
45  import org.junit.Rule;
46  import org.junit.Test;
47  import org.mockito.Mockito;
48  
49  /**
50   * Test case for {@link RtContents}.
51   * @author Andres Candal (andres.candal@rollasolution.com)
52   * @version $Id: d95ec4cecc5019071f29a2d8f26e137d20ac950a $
53   * @since 0.8
54   * @checkstyle MultipleStringLiteralsCheck (500 lines)
55   * @checkstyle ClassDataAbstractionCouplingCheck (500 lines)
56   */
57  @Immutable
58  @SuppressWarnings("PMD.AvoidDuplicateLiterals")
59  public final class RtContentsTest {
60  
61      /**
62       * The rule for skipping test if there's BindException.
63       * @checkstyle VisibilityModifierCheck (3 lines)
64       */
65      @Rule
66      public final transient RandomPort resource = new RandomPort();
67  
68      /**
69       * RtContents can fetch the default branch readme file.
70       *
71       * @throws Exception if some problem inside.
72       */
73      @Test
74      public void canFetchReadmeFile() throws Exception {
75          final String path = "README.md";
76          final JsonObject body = Json.createObjectBuilder()
77              .add("path", path)
78              .build();
79          try (
80              final MkContainer container = new MkGrizzlyContainer().next(
81                  new MkAnswer.Simple(HttpURLConnection.HTTP_OK, body.toString())
82              ).start(this.resource.port())) {
83              final RtContents contents = new RtContents(
84                  new ApacheRequest(container.home()),
85                  repo()
86              );
87              MatcherAssert.assertThat(
88                  contents.readme().path(),
89                  Matchers.is(path)
90              );
91              final MkQuery query = container.take();
92              MatcherAssert.assertThat(
93                  query.uri().toString(),
94                  Matchers.endsWith("/repos/test/contents/readme")
95              );
96              MatcherAssert.assertThat(
97                  query.body().length(),
98                  Matchers.is(0)
99              );
100         }
101     }
102 
103     /**
104      * RtContents can fetch the readme file from the specified branch.
105      *
106      * @throws Exception if a problem occurs.
107      */
108     @Test
109     public void canFetchReadmeFileFromSpecifiedBranch() throws Exception {
110         final String path = "README.md";
111         final JsonObject body = Json.createObjectBuilder()
112             .add("path", path)
113             .build();
114         try (final MkContainer container = new MkGrizzlyContainer().next(
115             new MkAnswer.Simple(HttpURLConnection.HTTP_OK, body.toString())
116         ).start(this.resource.port())) {
117             final RtContents contents = new RtContents(
118                 new ApacheRequest(container.home()),
119                 repo()
120             );
121             MatcherAssert.assertThat(
122                 contents.readme("test-branch").path(),
123                 Matchers.is(path)
124             );
125             final MkQuery query = container.take();
126             MatcherAssert.assertThat(
127                 query.uri().toString(),
128                 Matchers.endsWith("/repos/test/contents/readme")
129             );
130             MatcherAssert.assertThat(
131                 query.body(),
132                 Matchers.is("{\"ref\":\"test-branch\"}")
133             );
134         }
135     }
136 
137     /**
138      * RtContents can fetch files from the repository.
139      *
140      * @throws Exception if some problem inside.
141      * @checkstyle MultipleStringLiteralsCheck (50 lines)
142      */
143     @Test
144     public void canFetchFilesFromRepository() throws Exception {
145         final String path = "test/file";
146         final String name = "file";
147         final JsonObject body = Json.createObjectBuilder()
148             .add("path", path)
149             .add("name", name)
150             .build();
151         try (final MkContainer container = new MkGrizzlyContainer().next(
152             new MkAnswer.Simple(
153                 HttpURLConnection.HTTP_OK,
154                 Json.createObjectBuilder()
155                     .add("path", path)
156                     .add("name", name)
157                     .build().toString()
158             )
159         ).next(new MkAnswer.Simple(HttpURLConnection.HTTP_OK, body.toString()))
160             .start(this.resource.port())) {
161             final RtContents contents = new RtContents(
162                 new ApacheRequest(container.home()),
163                 repo()
164             );
165             final Content.Smart smart = new Content.Smart(
166                 contents.get(path, "branch1")
167             );
168             final MkQuery query = container.take();
169             MatcherAssert.assertThat(
170                 query.uri().toString(),
171                 Matchers.endsWith(
172                     "/repos/test/contents/contents/test/file?ref=branch1"
173                 )
174             );
175             MatcherAssert.assertThat(
176                 smart.path(),
177                 Matchers.is(path)
178             );
179             MatcherAssert.assertThat(
180                 smart.name(),
181                 Matchers.is(name)
182             );
183             MatcherAssert.assertThat(
184                 query.method(),
185                 Matchers.equalTo(Request.GET)
186             );
187             MatcherAssert.assertThat(
188                 container.take().uri().toString(),
189                 Matchers.endsWith(
190                     "/repos/test/contents/contents/test/file?ref=branch1"
191                 )
192             );
193         }
194     }
195 
196     /**
197      * RtContents can create a file in the repository.
198      * @throws Exception If a problem occurs.
199      */
200     @Test
201     public void canCreateFileInRepository() throws Exception {
202         final String path = "test/thefile";
203         final String name = "thefile";
204         final JsonObject body = Json.createObjectBuilder()
205             .add("path", path)
206             .add("name", name)
207             .build();
208         try (final MkContainer container = new MkGrizzlyContainer().next(
209             new MkAnswer.Simple(
210                 HttpURLConnection.HTTP_CREATED,
211                 Json.createObjectBuilder().add("content", body)
212                     .build().toString()
213             )
214         ).next(new MkAnswer.Simple(HttpURLConnection.HTTP_OK, body.toString()))
215             .start(this.resource.port())) {
216             final RtContents contents = new RtContents(
217                 new ApacheRequest(container.home()),
218                 repo()
219             );
220             final JsonObject content = Json.createObjectBuilder()
221                 .add("path", path)
222                 .add("message", "theMessage")
223                 .add("content", "blah")
224                 .build();
225             final Content.Smart smart = new Content.Smart(
226                 contents.create(content)
227             );
228             MatcherAssert.assertThat(
229                 container.take().uri().toString(),
230                 Matchers.endsWith(path)
231             );
232             MatcherAssert.assertThat(
233                 smart.path(),
234                 Matchers.is(path)
235             );
236             MatcherAssert.assertThat(
237                 smart.name(),
238                 Matchers.is(name)
239             );
240             MatcherAssert.assertThat(
241                 container.take().uri().toString(),
242                 Matchers.endsWith("/repos/test/contents/contents/test/thefile")
243             );
244         }
245     }
246 
247     /**
248      * RtContents can delete files from the repository.
249      *
250      * @throws Exception if a problem occurs.
251      * @checkstyle MultipleStringLiteralsCheck (50 lines)
252      */
253     @Test
254     public void canDeleteFilesFromRepository() throws Exception {
255         try (final MkContainer container = new MkGrizzlyContainer().next(
256             new MkAnswer.Simple(
257                 HttpURLConnection.HTTP_OK,
258                 Json.createObjectBuilder().add(
259                     "commit",
260                     Json.createObjectBuilder()
261                         .add("sha", "commitSha")
262                         .build()
263                 ).build().toString()
264             )
265         ).start(this.resource.port())) {
266             final RtContents contents = new RtContents(
267                 new ApacheRequest(container.home()),
268                 repo()
269             );
270             final RepoCommit commit = contents.remove(
271                 Json.createObjectBuilder()
272                     .add("path", "to/remove")
273                     .add("message", "Delete me")
274                     .add("sha", "fileSha")
275                     .build()
276             );
277             MatcherAssert.assertThat(
278                 commit.sha(),
279                 Matchers.is("commitSha")
280             );
281             final MkQuery query = container.take();
282             MatcherAssert.assertThat(
283                 query.body(),
284                 Matchers.allOf(
285                     Matchers.containsString("\"message\":\"Delete me\""),
286                     Matchers.containsString("\"sha\":\"fileSha\"")
287                 )
288             );
289             MatcherAssert.assertThat(
290                 query.uri().toString(),
291                 Matchers.endsWith("/repos/test/contents/contents/to/remove")
292             );
293         }
294     }
295 
296     /**
297      * RtContents can update files into the repository.
298      * @throws Exception If any problems during test execution occurs.
299      */
300     @Test
301     public void canUpdateFilesInRepository() throws Exception {
302         final String sha = "2f97253a513bbe26658881c29e27910082fef900";
303         final JsonObject resp = Json.createObjectBuilder()
304             // @checkstyle MultipleStringLiterals (1 line)
305             .add("sha", sha).build();
306         try (final MkContainer container = new MkGrizzlyContainer().next(
307             new MkAnswer.Simple(
308                 HttpURLConnection.HTTP_OK,
309                 Json.createObjectBuilder().add("commit", resp)
310                     .build().toString()
311             )
312         ).next(new MkAnswer.Simple(HttpURLConnection.HTTP_OK, resp.toString()))
313             .start(this.resource.port())) {
314             final RtContents contents = new RtContents(
315                 new ApacheRequest(container.home()),
316                 repo()
317             );
318             final String path = "test.txt";
319             final JsonObject json = Json.createObjectBuilder()
320                 .add("message", "let's change it.")
321                 .add("content", "bmV3IHRlc3Q=")
322                 .add("sha", "90b67dda6d5944ad167e20ec52bfed8fd56986c8")
323                 .build();
324             MatcherAssert.assertThat(
325                 new RepoCommit.Smart(contents.update(path, json)).sha(),
326                 Matchers.is(sha)
327             );
328             final MkQuery query = container.take();
329             MatcherAssert.assertThat(
330                 query.method(),
331                 Matchers.equalTo(Request.PUT)
332             );
333             MatcherAssert.assertThat(
334                 query.uri().getPath(),
335                 Matchers.endsWith(path)
336             );
337             MatcherAssert.assertThat(
338                 query.body(),
339                 Matchers.equalTo(json.toString())
340             );
341         }
342     }
343 
344     /**
345      * RtContents can iterate through a directory's contents.
346      * @throws Exception If something goes wrong.
347      */
348     @Test
349     public void canIterateDirectoryContents() throws Exception {
350         final JsonArray body = Json.createArrayBuilder().add(
351             Json.createObjectBuilder()
352                 .add("path", "README.md")
353                 .build()
354         ).add(
355             Json.createObjectBuilder()
356                 .add("path", ".gitignore")
357                 .build()
358         ).build();
359         try (final MkContainer container = new MkGrizzlyContainer().next(
360             new MkAnswer.Simple(HttpURLConnection.HTTP_OK, body.toString())
361         ).next(new MkAnswer.Simple("{\"path\":\"README.md\"}"))
362             .next(new MkAnswer.Simple("{\"path\":\".gitignore\"}"))
363             .start(this.resource.port())) {
364             final RtContents contents = new RtContents(
365                 new ApacheRequest(container.home()),
366                 repo()
367             );
368             MatcherAssert.assertThat(
369                 contents.iterate("dir", "branch2"),
370                 Matchers.<Content>iterableWithSize(2)
371             );
372         }
373     }
374 
375     /**
376      * Create and return repo for testing.
377      * @return Repo
378      */
379     private static Repo repo() {
380         final Repo repo = Mockito.mock(Repo.class);
381         Mockito.doReturn(new Coordinates.Simple("test", "contents"))
382             .when(repo).coordinates();
383         return repo;
384     }
385 }