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