View Javadoc
1   /**
2    * Copyright (c) 2013-2022, 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.mock;
31  
32  import com.jcabi.github.Content;
33  import com.jcabi.github.Contents;
34  import com.jcabi.github.Repo;
35  import com.jcabi.github.RepoCommit;
36  import com.jcabi.xml.XML;
37  import java.io.IOException;
38  import javax.json.Json;
39  import javax.json.JsonObject;
40  import javax.json.JsonObjectBuilder;
41  import org.hamcrest.MatcherAssert;
42  import org.hamcrest.Matchers;
43  import org.junit.Test;
44  
45  /**
46   * Test case for {@link MkContents}.
47   * @author Andres Candal (andres.candal@rollasolution.com)
48   * @version $Id: 79ed8f309294de403eb6354c30e61f49de55d61e $
49   * @since 0.8
50   * @checkstyle MultipleStringLiterals (500 lines)
51   */
52  @SuppressWarnings({ "PMD.TooManyMethods", "PMD.AvoidDuplicateLiterals" })
53  public final class MkContentsTest {
54      /**
55       * MkContents can fetch the default branch readme file.
56       * @throws Exception if some problem inside
57       */
58      @Test
59      public void canFetchReadmeFile() throws Exception {
60          final Contents contents = new MkGithub().randomRepo().contents();
61          final String body = "Readme On Master";
62          // @checkstyle MultipleStringLiterals (6 lines)
63          contents.create(
64              content("README.md", "readme on master", body).build()
65          );
66          MatcherAssert.assertThat(
67              contents.readme().json().getString("content"),
68              Matchers.is(body)
69          );
70      }
71  
72      /**
73       * MkContents should be able to fetch readme from a branch.
74       *
75       * @throws Exception if some problem inside
76       */
77      @Test
78      public void canFetchReadmeFromBranch() throws Exception {
79          final String branch = "branch-1";
80          final Contents contents = new MkGithub().randomRepo().contents();
81          final String body = "Readme On Branch";
82          contents.create(
83              content("README.md", "readme on branch", body)
84                  .add("ref", branch)
85                  .build()
86          );
87          MatcherAssert.assertThat(
88              contents.readme(branch).json().getString("content"),
89              Matchers.is(body)
90          );
91      }
92  
93      /**
94       * MkContents should be able to create new files.
95       *
96       * @throws Exception if some problem inside
97       */
98      @Test
99      public void canCreateFile() throws Exception {
100         final String path = "file.txt";
101         final Content.Smart content = new Content.Smart(
102             this.createFile(new MkGithub().randomRepo(), path)
103         );
104         MatcherAssert.assertThat(
105             content.path(),
106             Matchers.is(path)
107         );
108         MatcherAssert.assertThat(
109             content.name(),
110             Matchers.is(path)
111         );
112         MatcherAssert.assertThat(
113             content.sha(),
114             Matchers.not(Matchers.isEmptyOrNullString())
115         );
116     }
117 
118     /**
119      * MkContents can create new file in non default branch.
120      *
121      * @throws Exception if some problem inside
122      */
123     @Test
124     public void canCreateFileInSomeBranch() throws Exception {
125         final String path = "file-in-branch.txt";
126         final String branch = "branch-2";
127         final String body = "some file";
128         final Content.Smart content = new Content.Smart(
129             new MkGithub().randomRepo().contents().create(
130                 content(path, "some file", body)
131                     .add("ref", branch)
132                     .build()
133             )
134         );
135         MatcherAssert.assertThat(
136             content.path(),
137             Matchers.is(path)
138         );
139         MatcherAssert.assertThat(
140             content.name(),
141             Matchers.is(path)
142         );
143         MatcherAssert.assertThat(
144             content.sha(),
145             Matchers.not(Matchers.isEmptyOrNullString())
146         );
147         MatcherAssert.assertThat(
148             content.content(),
149             Matchers.is(body)
150         );
151     }
152 
153     /**
154      * MkContents should be able to create new files.
155      *
156      * @throws Exception if some problem inside
157      */
158     @Test
159     public void canRemoveFile() throws Exception {
160         final Repo repo = new MkGithub().randomRepo();
161         final String path = "removeme.txt";
162         this.createFile(repo, path);
163         final JsonObject json = MkContentsTest
164             .content(path, "theDeleteMessage")
165             .add("committer", MkContentsTest.committer())
166             .build();
167         final RepoCommit commit = repo.contents().remove(json);
168         MatcherAssert.assertThat(commit, Matchers.notNullValue());
169         MatcherAssert.assertThat(
170             commit.json().getString("message"),
171             Matchers.equalTo("theDeleteMessage")
172         );
173     }
174 
175     /**
176      * MkContents should be able to remove files from from non-default branches.
177      *
178      * @throws Exception if some problem inside
179      */
180     @Test
181     public void canRemoveFileFromBranch() throws Exception {
182         final String branch = "branch-1";
183         final Repo repo = new MkGithub().randomRepo();
184         final String path = "removeme.txt";
185         this.createFile(repo, path);
186         final JsonObject json = MkContentsTest
187             .content(path, "theDeleteMessage")
188             .add("ref", branch)
189             .add("committer", MkContentsTest.committer())
190             .build();
191         final RepoCommit commit = repo.contents().remove(json);
192         MatcherAssert.assertThat(commit, Matchers.notNullValue());
193         MatcherAssert.assertThat(
194             commit.json().getString("message"),
195             Matchers.equalTo("theDeleteMessage")
196         );
197     }
198 
199     /**
200      * MkContents should be able to update a file.
201      * @throws Exception - if anything goes wrong.
202      */
203     @Test
204     public void updatesFile() throws Exception {
205         final String path = "file.txt";
206         final String message = "content message";
207         final String initial = "initial text";
208         final String updated = "updated text";
209         final String cont = "content";
210         final Contents contents = new MkGithub().randomRepo().contents();
211         MatcherAssert.assertThat(
212             contents.create(
213                 MkContentsTest.content(path, message, initial).build()
214             ).json().getString(cont),
215             Matchers.is(initial)
216         );
217         contents.update(
218             path, MkContentsTest.content(path, message, updated).build()
219         );
220         MatcherAssert.assertThat(
221             contents.get(path, "master").json().getString(cont),
222             Matchers.is(updated)
223         );
224     }
225 
226     /**
227      * MkContents is able to update the file content.
228      * During update new commit is created
229      * @throws Exception Exception if some problem inside
230      */
231     @Test
232     public void updatesFileCreateCommit() throws Exception {
233         final MkStorage storage = new MkStorage.InFile();
234         final Contents contents = MkContentsTest.repo(storage).contents();
235         final String path = "file.txt";
236         final JsonObject json = MkContentsTest
237             .content(path, "theCreateMessage", "newContent")
238             .add("committer", MkContentsTest.committer())
239             .build();
240         contents.create(json);
241         final String xpath = "/github/repos/repo/commits/commit";
242         MatcherAssert.assertThat(
243             storage.xml().nodes(xpath),
244             Matchers.<XML>iterableWithSize(1)
245         );
246         final JsonObject update = MkContentsTest
247             .content(path, "theMessage", "blah")
248             .build();
249         MatcherAssert.assertThat(
250             new RepoCommit.Smart(contents.update(path, update)).sha(),
251             Matchers.not(Matchers.isEmptyOrNullString())
252         );
253         MatcherAssert.assertThat(
254             new Content.Smart(contents.get(path, "master")).path(),
255             Matchers.is(path)
256         );
257         MatcherAssert.assertThat(
258             storage.xml().nodes(xpath),
259             Matchers.<XML>iterableWithSize(2)
260         );
261     }
262 
263     /**
264      * MkContents can update an content.
265      * @throws Exception if any problem inside
266      */
267     @Test
268     public void updateContent() throws Exception {
269         final String path = "content-to-update.txt";
270         final String message = "commit message";
271         final String initial = "Hello World!";
272         final String updated = "update content";
273         final String branch = "master";
274         final Contents contents = new MkGithub().randomRepo().contents();
275         final JsonObject content = MkContentsTest
276             .content(path, message, initial)
277             .add("ref", branch)
278             .build();
279         MatcherAssert.assertThat(
280             new Content.Smart(contents.create(content)).content(),
281             Matchers.is(initial)
282         );
283         contents.update(
284             path, MkContentsTest.content(path, message, updated)
285                 .add("ref", branch).build()
286         );
287         MatcherAssert.assertThat(
288             new Content.Smart(contents.get(path, branch)).content(),
289             Matchers.is(updated)
290         );
291     }
292 
293     /**
294      * MkContents can check whether content exists or not.
295      * @throws Exception if any problem inside.
296      */
297     @Test
298     public void checkExists() throws Exception {
299         final String path = "content-exist.txt";
300         final String branch = "rel.08";
301         final Contents contents = new MkGithub().randomRepo().contents();
302         contents.create(
303             MkContentsTest.content(path, "commit", "content exists")
304                 .add("ref", branch)
305                 .build()
306         );
307         MatcherAssert.assertThat(
308             contents.exists(path, branch),
309             Matchers.is(true)
310         );
311         MatcherAssert.assertThat(
312             contents.exists("content-not-exist.txt", branch),
313             Matchers.is(false)
314         );
315     }
316 
317     /**
318      * MkContents can get content from default branch.
319      * @throws Exception if any problem inside
320      */
321     @Test
322     public void getContentFromDefaultBranch() throws Exception {
323         final String path = "content-default-branch.txt";
324         final String message = "content default branch created";
325         final String text = "I'm content of default branch";
326         final Contents contents = new MkGithub().randomRepo().contents();
327         final JsonObject content = MkContentsTest
328             .content(path, message, text)
329             .build();
330         MatcherAssert.assertThat(
331             new Content.Smart(contents.create(content)).content(),
332             Matchers.is(text)
333         );
334         MatcherAssert.assertThat(
335             new Content.Smart(contents.get(path)).content(),
336             Matchers.is(text)
337         );
338     }
339 
340     /**
341      * Tests if MkContents is iterable by path.
342      * @throws IOException if any error occurs.
343      */
344     @Test
345     public void canIterate() throws IOException {
346         final MkStorage storage = new MkStorage.InFile();
347         final Repo repo = repo(storage);
348         final Content[] correct = this.addContent(
349             repo, "foo/bar/1", "foo/bar/2"
350         );
351         this.addContent(repo, "foo/baz", "foo/boo");
352         MatcherAssert.assertThat(
353             repo.contents().iterate("foo/bar", "ref-1"),
354             Matchers.contains(correct)
355         );
356     }
357 
358     /**
359      * Adds colection of test content items.
360      * @param repo The repo.
361      * @param paths Test items to be created inside the repo.
362      * @return Iterable with created items.
363      * @throws IOException If any I/O error occurs.
364      */
365     private Content[] addContent(final Repo repo,
366         final String... paths) throws IOException {
367         final Content[] result = new Content[paths.length];
368         int index = 0;
369         for (final String path : paths) {
370             result[index] = repo.contents().create(
371                 Json.createObjectBuilder().add("ref", "ref-1")
372                     .add("path", path).add("content", path)
373                     .add("message", "msg").build()
374             );
375             index += 1;
376         }
377         return result;
378     }
379 
380     /**
381      * Creates a new file.
382      * @param repo The repository
383      * @param path Content path
384      * @return Created content
385      * @throws Exception if some problem inside
386      */
387     private Content createFile(
388         final Repo repo, final String path) throws Exception {
389         final Contents contents = repo.contents();
390         final JsonObject json = MkContentsTest
391             .content(path, "theCreateMessage", "newContent")
392             .add("committer", MkContentsTest.committer())
393             .build();
394         return contents.create(json);
395     }
396 
397     /**
398      * Create content JsonObjectBuilder.
399      * @param path Content path
400      * @param message Commit message
401      * @return JsonObjectBuilder
402      * @throws Exception If some problem inside
403      */
404     private static JsonObjectBuilder content(
405         final String path, final String message)
406         throws Exception {
407         return Json.createObjectBuilder()
408             .add("path", path)
409             .add("message", message);
410     }
411 
412     /**
413      * Create content JsonObjectBuilder.
414      * @param path Content path
415      * @param message Commit message
416      * @param content Base64 encoded content
417      * @return JsonObjectBuilder
418      * @throws Exception If some problem inside
419      */
420     private static JsonObjectBuilder content(
421         final String path, final String message, final String content)
422         throws Exception {
423         return Json.createObjectBuilder()
424             .add("path", path)
425             .add("message", message)
426             .add("content", content);
427     }
428 
429     /**
430      * Creates default committer.
431      * @return JsonObjectBuilder
432      */
433     private static JsonObjectBuilder committer() {
434         return Json.createObjectBuilder()
435             .add("name", "joe")
436             .add("email", "joe@contents.com");
437     }
438 
439     /**
440      * Create a test repo with custom {@code MkStorage}.
441      * @param storage The storage
442      * @return Test repo
443      * @throws IOException If any I/O error occurs.
444      */
445     private static Repo repo(
446         final MkStorage storage) throws IOException {
447         final String login = "test";
448         return new MkGithub(storage, login).randomRepo();
449     }
450 
451 }