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.OAuthScope.Scope;
34  import javax.json.Json;
35  import javax.json.JsonObject;
36  import org.apache.commons.codec.binary.Base64;
37  import org.apache.commons.lang3.RandomStringUtils;
38  import org.hamcrest.MatcherAssert;
39  import org.hamcrest.Matchers;
40  import org.junit.Ignore;
41  import org.junit.Rule;
42  import org.junit.Test;
43  
44  /**
45   * Test case for {@link RtContents}.
46   * @author Andres Candal (andres.candal@rollasolution.com)
47   * @version $Id: ec3691f8b831919362e36513783504e77e95caba $
48   * @since 0.8
49   * @checkstyle MultipleStringLiterals (500 lines)
50   */
51  @OAuthScope(Scope.REPO)
52  @SuppressWarnings("PMD.AvoidDuplicateLiterals")
53  public final class RtContentsITCase {
54  
55      /**
56       * RepoRule.
57       * @checkstyle VisibilityModifierCheck (3 lines)
58       */
59      @Rule
60      public final transient RepoRule rule = new RepoRule();
61  
62      /**
63       * RtContents can fetch readme file.
64       * @throws Exception If some problem inside
65       */
66      @Test
67      public void canFetchReadmeFiles() throws Exception {
68          final Repos repos = new GithubIT().connect().repos();
69          final Repo repo = this.rule.repo(repos);
70          try {
71              MatcherAssert.assertThat(
72                  repos.get(repo.coordinates()).contents().readme().path(),
73                  Matchers.equalTo("README.md")
74              );
75          } finally {
76              repos.remove(repo.coordinates());
77          }
78      }
79  
80      /**
81       * RtContents can get update file content.
82       * @throws Exception If some problem inside
83       */
84      @Test
85      public void canUpdateFileContent() throws Exception {
86          final Repos repos = new GithubIT().connect().repos();
87          final Repo repo = this.rule.repo(repos);
88          final Contents contents = repos.get(repo.coordinates()).contents();
89          final String message = "commit message";
90          final String text = "new content";
91          try {
92              final String path = RandomStringUtils.randomAlphanumeric(Tv.TEN);
93              final Content content = contents.create(
94                  this.jsonObject(
95                      path, new String(
96                          Base64.encodeBase64("init content".getBytes())
97                      ),
98                      message
99                  )
100             );
101             contents.update(
102                 path,
103                 Json.createObjectBuilder()
104                     .add("path", path)
105                     .add("message", message)
106                     .add("content", Base64.encodeBase64String(text.getBytes()))
107                     .add("sha", new Content.Smart(content).sha()).build()
108             );
109             MatcherAssert.assertThat(
110                 new String(
111                     Base64.decodeBase64(
112                         new Content.Smart(
113                             contents.get(path, "master")
114                         ).content()
115                     )
116                 ),
117                 Matchers.equalTo(text)
118             );
119         } finally {
120             repos.remove(repo.coordinates());
121         }
122     }
123 
124     /**
125      * RtContents can get update file content in specific branch.
126      * @throws Exception If some problem inside
127      */
128     @Test
129     public void canUpdateFileContentInSpecificBranch() throws Exception {
130         final Repos repos = new GithubIT().connect().repos();
131         final Repo repo = this.rule.repo(repos);
132         final Contents contents = repos.get(repo.coordinates()).contents();
133         final String message = "Commit message";
134         final String text = "Updated";
135         try {
136             final String path = RandomStringUtils.randomAlphanumeric(Tv.TEN);
137             final Content content = contents.create(
138                 this.jsonObject(
139                     path, new String(
140                         Base64.encodeBase64("Initial.".getBytes())
141                     ),
142                     message
143                 )
144             );
145             contents.update(
146                 path,
147                 Json.createObjectBuilder()
148                     .add("path", path)
149                     .add("message", message)
150                     .add("ref", "master")
151                     .add("content", Base64.encodeBase64String(text.getBytes()))
152                     .add("sha", new Content.Smart(content).sha()).build()
153             );
154             MatcherAssert.assertThat(
155                 new String(
156                     Base64.decodeBase64(
157                         new Content.Smart(
158                             contents.get(path, "master")
159                         ).content()
160                     )
161                 ),
162                 Matchers.equalTo(text)
163             );
164         } finally {
165             repos.remove(repo.coordinates());
166         }
167     }
168 
169     /**
170      * RtContents can remove and throw an exception when get an absent content.
171      * @throws Exception If some problem inside
172      */
173     @Test(expected = AssertionError.class)
174     public void throwsWhenTryingToGetAnAbsentContent() throws Exception {
175         final Repos repos = new GithubIT().connect().repos();
176         final Repo repo = this.rule.repo(repos);
177         final Contents contents = repos.get(repo.coordinates()).contents();
178         final String message = "commit message";
179         try {
180             final String path = RandomStringUtils.randomAlphanumeric(Tv.TEN);
181             final Content content = contents.create(
182                 this.jsonObject(
183                     path, new String(
184                         Base64.encodeBase64("first content".getBytes())
185                     ),
186                     message
187                 )
188             );
189             contents.remove(
190                 Json.createObjectBuilder()
191                     .add("path", path)
192                     .add("message", message)
193                     .add("sha", new Content.Smart(content).sha()).build()
194             );
195             contents.get(path, "master");
196         } finally {
197             repos.remove(repo.coordinates());
198         }
199     }
200 
201     /**
202      * RtContents can create file content.
203      * @throws Exception If some problem inside
204      */
205     @Test
206     public void canCreateFileContent() throws Exception {
207         final Repos repos = new GithubIT().connect().repos();
208         final Repo repo = this.rule.repo(repos);
209         try {
210             final String path = RandomStringUtils.randomAlphanumeric(Tv.TEN);
211             MatcherAssert.assertThat(
212                 repos.get(repo.coordinates()).contents().create(
213                     this.jsonObject(
214                         path, new String(
215                             Base64.encodeBase64("some content".getBytes())
216                         ), "theMessage"
217                     )
218                 ).path(),
219                 Matchers.equalTo(path)
220             );
221         } finally {
222             repos.remove(repo.coordinates());
223         }
224     }
225 
226     /**
227      * RtContents can get content.
228      * @throws Exception If some problem inside
229      */
230     @Test
231     public void getContent() throws Exception {
232         final Repos repos = new GithubIT().connect().repos();
233         final Repo repo = this.rule.repo(repos);
234         try {
235             final String path = RandomStringUtils.randomAlphanumeric(Tv.TEN);
236             final String message = String.format("testMessage");
237             final String cont = new String(
238                 Base64.encodeBase64(
239                     String.format("content%d", System.currentTimeMillis())
240                         .getBytes()
241                 )
242             );
243             final Contents contents = repos.get(repo.coordinates()).contents();
244             contents.create(this.jsonObject(path, cont, message));
245             final Content content = contents.get(path, "master");
246             MatcherAssert.assertThat(
247                 content.path(),
248                 Matchers.equalTo(path)
249             );
250             MatcherAssert.assertThat(
251                 new Content.Smart(content).content(),
252                 Matchers.equalTo(String.format("%s\n", cont))
253             );
254             final Content other = contents.get(path);
255             MatcherAssert.assertThat(content, Matchers.equalTo(other));
256         } finally {
257             repos.remove(repo.coordinates());
258         }
259     }
260 
261     /**
262      * RtContents can iterate content.
263      * @throws Exception If some problem inside
264      * @todo #863 unignore after Contents#get is implemented for
265      *  directories (#968 and #903)
266      */
267     @Test
268     @Ignore
269     public void iteratesContent() throws Exception {
270         final Repos repos = new GithubIT().connect().repos();
271         final Repo repo = this.rule.repo(repos);
272         try {
273             final String afile = RandomStringUtils.randomAlphanumeric(Tv.TEN);
274             final String dir = RandomStringUtils.randomAlphanumeric(Tv.TEN);
275             final String bfile = String.format(
276                 "%s/%s",
277                 dir,
278                 RandomStringUtils.randomAlphanumeric(Tv.TEN)
279             );
280             final String message = String.format("testMessage");
281             final Contents contents = repos.get(repo.coordinates()).contents();
282             contents.create(
283                 this.jsonObject(
284                     afile,
285                     new String(
286                         Base64.encodeBase64(
287                             String.format(
288                                 "content a:%d",
289                                 System.currentTimeMillis()
290                             ).getBytes()
291                         )
292                     ),
293                     message
294                 )
295             );
296             contents.create(
297                 this.jsonObject(
298                     bfile,
299                     new String(
300                         Base64.encodeBase64(
301                             String.format(
302                                 "content b:%d",
303                                 System.currentTimeMillis()
304                             ).getBytes()
305                         )
306                     ),
307                     message
308                 )
309             );
310             final Iterable<Content> iterated = contents.iterate("", "master");
311             MatcherAssert.assertThat(
312                 iterated,
313                 Matchers.allOf(
314                     Matchers.hasItems(contents.get(afile), contents.get(dir)),
315                     Matchers.<Content>iterableWithSize(Tv.THREE)
316                 )
317             );
318         } finally {
319             repos.remove(repo.coordinates());
320         }
321     }
322 
323     /**
324      * RtContents can check whether content exists or not.
325      * @throws Exception if any problem inside.
326      */
327     @Test
328     public void checkExists() throws Exception {
329         final Repos repos = new GithubIT().connect().repos();
330         final Repo repo = this.rule.repo(repos);
331         final String branch = "master";
332         try {
333             final String path = RandomStringUtils.randomAlphanumeric(Tv.TEN);
334             final String cont = new String(
335                 Base64.encodeBase64(
336                     String.format("exist%d", System.currentTimeMillis())
337                         .getBytes()
338                 )
339             );
340             final Contents contents = repos.get(repo.coordinates()).contents();
341             contents.create(this.jsonObject(path, cont, "test exist"));
342             MatcherAssert.assertThat(
343                 contents.exists(path, branch),
344                 Matchers.is(true)
345             );
346             MatcherAssert.assertThat(
347                 contents.exists("content-not-exist.txt", branch),
348                 Matchers.is(false)
349             );
350         } finally {
351             repos.remove(repo.coordinates());
352         }
353     }
354 
355     /**
356      * Create and return JsonObject of content.
357      * @param path Content's path
358      * @param cont Content's Base64 string
359      * @param message Message
360      * @return JsonObject
361      */
362     private JsonObject jsonObject(
363         final String path, final String cont, final String message
364     ) {
365         return Json.createObjectBuilder()
366             .add("path", path)
367             .add("message", message)
368             .add("content", cont)
369             .add("ref", "master")
370             .build();
371     }
372 
373 }