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.http.Response;
33  import com.jcabi.http.mock.MkAnswer;
34  import com.jcabi.http.mock.MkContainer;
35  import com.jcabi.http.mock.MkGrizzlyContainer;
36  import com.jcabi.http.request.ApacheRequest;
37  import com.jcabi.http.request.FakeRequest;
38  import com.jcabi.http.response.JsonResponse;
39  import java.util.EnumMap;
40  import javax.json.Json;
41  import javax.json.JsonArrayBuilder;
42  import javax.json.JsonObject;
43  import javax.json.JsonObjectBuilder;
44  import org.hamcrest.MatcherAssert;
45  import org.hamcrest.Matchers;
46  import org.junit.Rule;
47  import org.junit.Test;
48  
49  /**
50   * Test case for {@link RtSearch}.
51   *
52   * @author Carlos Miranda (miranda.cma@gmail.com)
53   * @author Paulo Lobo (pauloeduardolobo@gmail.com)
54   * @version $Id: f7d1830a2d1366c6b53ae0a10f68125c12dff40d $
55   * @checkstyle MultipleStringLiterals (300 lines)
56   * @checkstyle ClassDataAbstractionCouplingCheck (3 lines)
57   */
58  @SuppressWarnings("PMD.AvoidDuplicateLiterals")
59  public final class RtSearchTest {
60      /**
61       * The rule for skipping test if there's BindException.
62       * @checkstyle VisibilityModifierCheck (3 lines)
63       */
64      @Rule
65      public final transient RandomPort resource = new RandomPort();
66  
67      /**
68       * RtSearch can search for repos.
69       *
70       */
71      @Test
72      public void canSearchForRepos() {
73          final String coords = "test-user1/test-repo1";
74          final Search search = new RtGithub(
75              new FakeRequest().withBody(
76                  RtSearchTest.search(
77                      Json.createObjectBuilder().add("full_name", coords).build()
78                  ).toString()
79              )
80          ).search();
81          MatcherAssert.assertThat(
82              search.repos("test", "stars", Search.Order.DESC).iterator().next()
83                  .coordinates().toString(),
84              Matchers.equalTo(coords)
85          );
86      }
87  
88      /**
89       * RtSearch can search for issues.
90       *
91       */
92      @Test
93      public void canSearchForIssues() {
94          final int number = 1;
95          final Search search = new RtGithub(
96              new FakeRequest().withBody(
97                  RtSearchTest.search(
98                      Json.createObjectBuilder().add(
99                          "url", String.format(
100                             // @checkstyle LineLength (1 line)
101                             "https://api.github.com/repos/user/repo/issues/%s",
102                             number
103                         )
104                     ).add("number", number).build()
105                 ).toString()
106             )
107         ).search();
108         MatcherAssert.assertThat(
109             search.issues(
110                 "test2",
111                 "created",
112                 Search.Order.DESC,
113                 new EnumMap<>(Search.Qualifier.class)
114             ).iterator().next().number(),
115             Matchers.equalTo(number)
116         );
117     }
118 
119     /**
120      * RtSearch can search for users.
121      *
122      * @throws Exception if a problem occurs
123      */
124     @Test
125     public void canSearchForUsers() throws Exception {
126         final String login = "test-user";
127         final Search search = new RtGithub(
128             new FakeRequest().withBody(
129                 RtSearchTest.search(
130                     Json.createObjectBuilder()
131                         .add("login", login).build()
132                 ).toString()
133             )
134         ).search();
135         MatcherAssert.assertThat(
136             search.users("test3", "joined", Search.Order.DESC)
137                 .iterator().next().login(),
138             Matchers.equalTo(login)
139         );
140     }
141 
142     /**
143      * RtSearch can search for contents.
144      *
145      * @throws Exception if a problem occurs
146      */
147     @Test
148     public void canSearchForContents() throws Exception {
149         final JsonObject first = RtSearchTest.content(
150             "test/unit/attributes.js",
151             "attributes.js",
152             // @checkstyle LineLength (1 line)
153             "https://api.github.com/repos/user/repo/contents/test/unit/attributes.js?ref=f3b89ba0820882bd4ce4404b7e7c819e7b506de5"
154         ).build();
155         final JsonObject second = RtSearchTest.content(
156             "src/attributes/classes.js",
157             "classes.js",
158             // @checkstyle LineLength (1 line)
159             "https://api.github.com/repos/user/repo/contents/src/attributes/classes.js?ref=f3b89ba0820882bd4ce4404b7e7c819e7b506de5"
160         ).build();
161         try (
162             final MkContainer container = new MkGrizzlyContainer().next(
163                 new MkAnswer.Simple(
164                     RtSearchTest.search(first, second).toString()
165                 )
166             ).next(new MkAnswer.Simple(first.toString()))
167                 .next(new MkAnswer.Simple(second.toString()))
168                 .start(this.resource.port())
169         ) {
170             final Search search = new RtGithub(
171                 new ApacheRequest(container.home())
172             ).search();
173             MatcherAssert.assertThat(
174                 search.codes("test4", "joined", Search.Order.DESC),
175                 Matchers.<Content>iterableWithSize(2)
176             );
177             container.stop();
178         }
179     }
180 
181     /**
182      * RtSearch can read non-unicode.
183      * @throws Exception if any problem inside
184      */
185     @Test
186     public void readNonUnicode() throws Exception {
187         final Response resp = new FakeRequest()
188             .withBody("{\"help\": \"\u001Fblah\u0001cwhoa\u0000!\"}").fetch();
189         final JsonResponse response = new JsonResponse(resp);
190         MatcherAssert.assertThat(
191             response.json().readObject().getString("help"),
192             Matchers.is("\u001Fblah\u0001cwhoa\u0000!")
193         );
194     }
195 
196     /**
197      * Create content JsonObject.
198      * @param path Content path
199      * @param name Content name
200      * @param url Content url
201      * @return JsonObjectBuilder
202      */
203     private static JsonObjectBuilder content(
204         final String path, final String name, final String url) {
205         return Json.createObjectBuilder()
206             .add("path", path)
207             .add("name", name)
208             .add("url", url);
209     }
210 
211     /**
212      * Create search response JsonObjectBuilder.
213      * @param contents Contents to add
214      * @return JsonObject
215      */
216     private static JsonObject search(
217         final JsonObject ... contents) {
218         final JsonArrayBuilder builder = Json.createArrayBuilder();
219         for (final JsonObject content : contents) {
220             builder.add(content);
221         }
222         return Json.createObjectBuilder()
223             .add("total_count", contents.length)
224             .add("items", builder).build();
225     }
226 }