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.mock.MkGithub;
34  import com.jcabi.http.Request;
35  import com.jcabi.http.mock.MkAnswer;
36  import com.jcabi.http.mock.MkContainer;
37  import com.jcabi.http.mock.MkGrizzlyContainer;
38  import com.jcabi.http.request.ApacheRequest;
39  import com.jcabi.http.request.FakeRequest;
40  import java.net.HttpURLConnection;
41  import java.util.Date;
42  import javax.json.Json;
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 RtUser}.
51   * @author Giang Le (giang@vn-smartsolutions.com)
52   * @version $Id: 874346cd2e0ef9d68ea10d43ad5d076885761057 $
53   * @checkstyle MultipleStringLiterals (500 lines)
54   * @checkstyle ClassDataAbstractionCouplingCheck (500 lines)
55   * @checkstyle LineLengthCheck (500 lines)
56   * @checkstyle MagicNumberCheck (500 lines)
57   * @checkstyle MethodNameCheck (500 lines)
58   */
59  @SuppressWarnings({"PMD.AvoidDuplicateLiterals", "PMD.TooManyMethods" })
60  public final class RtUserTest {
61  
62      /**
63       * The rule for skipping test if there's BindException.
64       * @checkstyle VisibilityModifierCheck (3 lines)
65       */
66      @Rule
67      public final transient RandomPort resource = new RandomPort();
68  
69      /**
70       * RtUser can understand who am I.
71       * @throws Exception If some problem inside
72       */
73      @Test
74      public void checksWhoAmI() throws Exception {
75          final String login = "monalia";
76          final RtUser user = new RtUser(
77              Mockito.mock(Github.class),
78              new FakeRequest().withBody(
79                  Json.createObjectBuilder()
80                      .add("login", login)
81                      .build().toString()
82              )
83          );
84          MatcherAssert.assertThat(
85              user.login(),
86              Matchers.equalTo(login)
87          );
88      }
89  
90      /**
91       * RtUser can check if he has a name.
92       * @throws Exception If some problem inside
93       */
94      @Test
95      public void checksIfHeHasAName() throws Exception {
96          final User.Smart smart = new User.Smart(
97              new RtUser(
98                  Mockito.mock(Github.class),
99                  new FakeRequest().withBody(
100                     Json.createObjectBuilder()
101                         .add("name", "octoc")
102                         .build()
103                         .toString()
104                 ),
105                 "octoc"
106             )
107         );
108         MatcherAssert.assertThat(
109             smart.hasName(),
110             Matchers.equalTo(true)
111         );
112     }
113 
114     /**
115      * RtUser can check if he has NO name.
116      * @throws Exception If some problem inside
117      */
118     @Test
119     public void checksIfHeHasNoName() throws Exception {
120         final User.Smart smart = new User.Smart(
121             new RtUser(
122                 Mockito.mock(Github.class),
123                 new FakeRequest().withBody(
124                     Json.createObjectBuilder()
125                         .build()
126                         .toString()
127                 ),
128                 "octoc"
129             )
130         );
131         MatcherAssert.assertThat(
132             smart.hasName(),
133             Matchers.equalTo(false)
134         );
135     }
136 
137     /**
138      * RtUser can describe as a JSON object.
139      *
140      * @throws Exception if there is any problem
141      */
142     @Test
143     public void describeAsJson() throws Exception {
144         final RtUser user = new RtUser(
145             Mockito.mock(Github.class),
146             new FakeRequest().withBody(
147                 Json.createObjectBuilder()
148                     .add("name", "monalisa")
149                     .add("email", "octocat@github.com")
150                     .build()
151                     .toString()
152             ),
153             "octoc"
154         );
155         MatcherAssert.assertThat(
156             user.json().toString(),
157             Matchers.equalTo(
158                 "{\"name\":\"monalisa\",\"email\":\"octocat@github.com\"}"
159             )
160         );
161     }
162 
163     /**
164      * RtUser can execute PATCH request.
165      *
166      * @throws Exception if there is any problem
167      */
168     @Test
169     public void executePatchRequest() throws Exception {
170         final MkContainer container = new MkGrizzlyContainer().next(
171             new MkAnswer.Simple(
172                 HttpURLConnection.HTTP_OK,
173                 "{\"login\":\"octocate\"}"
174             )
175         ).start(this.resource.port());
176         final RtUser json = new RtUser(
177             Mockito.mock(Github.class),
178             new ApacheRequest(container.home())
179         );
180         json.patch(
181             Json.createObjectBuilder()
182                 .add("location", "San Francisco")
183                 .build()
184         );
185         MatcherAssert.assertThat(
186             container.take().method(),
187             Matchers.equalTo(Request.PATCH)
188         );
189         container.stop();
190     }
191 
192     /**
193      * RtUser can fetch emails.
194      */
195     @Test
196     public void fetchesEmails() {
197         final Github github = Mockito.mock(Github.class);
198         Mockito.when(github.entry()).thenReturn(new FakeRequest());
199         final User user = new RtUser(github, new FakeRequest());
200         MatcherAssert.assertThat(user.emails(), Matchers.notNullValue());
201     }
202 
203     /**
204      * RtUser can fetch organizations.
205      */
206     @Test
207     public void fetchesOrganizations() {
208         final Github github = Mockito.mock(Github.class);
209         Mockito.when(github.entry()).thenReturn(new FakeRequest());
210         final User user = new RtUser(github, new FakeRequest());
211         MatcherAssert.assertThat(user.organizations(), Matchers.notNullValue());
212     }
213 
214     /**
215      * Tests if a User.Smart object handles html_url JSON property.
216      * @throws Exception if any problem occurs.
217      */
218     @Test
219     public void hasHtmlUrl() throws Exception {
220         final String value = "http://github.example.com";
221         final User.Smart smart = this.userWith("html_url", value);
222         MatcherAssert.assertThat(smart.htmlUrl(), Matchers.is(value));
223     }
224 
225     /**
226      * Tests if a User.Smart object handles followers_url JSON property.
227      * @throws Exception if any problem occurs.
228      */
229     @Test
230     public void hasFollwersUrl() throws Exception {
231         final String value = "http://github.example.com/followers";
232         final User.Smart smart = this.userWith("followers_url", value);
233         MatcherAssert.assertThat(smart.followersUrl(), Matchers.is(value));
234     }
235 
236     /**
237      * Tests if a User.Smart object handles following_url JSON property.
238      * @throws Exception if any problem occurs.
239      */
240     @Test
241     public void hasFollowingUrl() throws Exception {
242         final String value = "http://github.example.com/following";
243         final User.Smart smart = this.userWith("following_url", value);
244         MatcherAssert.assertThat(smart.followingUrl(), Matchers.is(value));
245     }
246 
247     /**
248      * Tests if a User.Smart object handles gists_url JSON property.
249      * @throws Exception if any problem occurs.
250      */
251     @Test
252     public void hasGistsUrl() throws Exception {
253         final String value = "http://github.example.com/gists";
254         final User.Smart smart = this.userWith("gists_url", value);
255         MatcherAssert.assertThat(smart.gistsUrl(), Matchers.is(value));
256     }
257 
258     /**
259      * Tests if a User.Smart object handles starred_url JSON property.
260      * @throws Exception if any problem occurs.
261      */
262     @Test
263     public void hasStarredUrl() throws Exception {
264         final String value = "http://github.example.com/starred";
265         final User.Smart smart = this.userWith("starred_url", value);
266         MatcherAssert.assertThat(smart.starredUrl(), Matchers.is(value));
267     }
268 
269     /**
270      * Tests if a User.Smart object handles subscriptions_url JSON property.
271      * @throws Exception if any problem occurs.
272      */
273     @Test
274     public void hasSubscriptionsUrl() throws Exception {
275         final String value = "http://github.example.com/subscriptions";
276         final User.Smart smart = this.userWith("subscriptions_url", value);
277         MatcherAssert.assertThat(smart.subscriptionsUrl(), Matchers.is(value));
278     }
279 
280     /**
281      * Tests if a User.Smart object handles organizations_url JSON property.
282      * @throws Exception if any problem occurs.
283      */
284     @Test
285     public void hasOrganizationsUrl() throws Exception {
286         final String value = "http://github.example.com/organizations";
287         final User.Smart smart = this.userWith("organizations_url", value);
288         MatcherAssert.assertThat(smart.organizationsUrl(), Matchers.is(value));
289     }
290 
291     /**
292      * Tests if a User.Smart object handles repos_url JSON property.
293      * @throws Exception if any problem occurs.
294      */
295     @Test
296     public void hasReposUrl() throws Exception {
297         final String value = "http://github.example.com/repos";
298         final User.Smart smart = this.userWith("repos_url", value);
299         MatcherAssert.assertThat(smart.reposUrl(), Matchers.is(value));
300     }
301 
302     /**
303      * Tests if a User.Smart object handles events_url JSON property.
304      * @throws Exception if any problem occurs.
305      */
306     @Test
307     public void hasEventsUrl() throws Exception {
308         final String value = "http://github.example.com/events";
309         final User.Smart smart = this.userWith("events_url", value);
310         MatcherAssert.assertThat(smart.eventsUrl(), Matchers.is(value));
311     }
312 
313     /**
314      * Tests if a User.Smart object handles received_events_url JSON property.
315      * @throws Exception if any problem occurs.
316      */
317     @Test
318     public void hasReceivedEventsUrl() throws Exception {
319         final String value = "http://github.example.com/received_events";
320         final User.Smart smart = this.userWith("received_events_url", value);
321         MatcherAssert.assertThat(smart.receivedEventsUrl(), Matchers.is(value));
322     }
323 
324     /**
325      * Tests if a User.Smart object handles type JSON property.
326      * @throws Exception if any problem occurs.
327      */
328     @Test
329     public void hasType() throws Exception {
330         final String value = "http://github.example.com/organizations";
331         final User.Smart smart = this.userWith("type", value);
332         MatcherAssert.assertThat(smart.type(), Matchers.is(value));
333     }
334 
335     /**
336      * Tests if a User.Smart object handles site_admin JSON property.
337      * @throws Exception if any problem occurs.
338      */
339     @Test
340     public void hasSiteAdmin() throws Exception {
341         final User.Smart smart = this.userWith("site_admin", "true");
342         MatcherAssert.assertThat(smart.siteAdmin(), Matchers.is(true));
343     }
344 
345     /**
346      * Tests if a User.Smart object handles blog JSON property.
347      * @throws Exception if any problem occurs.
348      */
349     @Test
350     public void hasBlog() throws Exception {
351         final String value = "http://blog.example.com";
352         final User.Smart smart = this.userWith("blog", value);
353         MatcherAssert.assertThat(smart.blog(), Matchers.is(value));
354     }
355 
356     /**
357      * Tests if a User.Smart object handles hireable JSON property.
358      * @throws Exception if any problem occurs.
359      */
360     @Test
361     public void hasHireable() throws Exception {
362         final User.Smart smart = this.userWith("hireable", "true");
363         MatcherAssert.assertThat(smart.hireable(), Matchers.is(true));
364     }
365 
366     /**
367      * Tests if a User.Smart object handles bio JSON property.
368      * @throws Exception if any problem occurs.
369      */
370     @Test
371     public void hasBio() throws Exception {
372         final String value = "http://github.example.com/bio";
373         final User.Smart smart = this.userWith("bio", value);
374         MatcherAssert.assertThat(smart.bio(), Matchers.is(value));
375     }
376 
377     /**
378      * Tests if a User.Smart object handles public_repos JSON property.
379      * @throws Exception if any problem occurs.
380      */
381     @Test
382     public void hasPublicRepos() throws Exception {
383         final int value = Tv.THREE;
384         final User.Smart smart = this.userWith(
385             "public_repos",
386             String.valueOf(value)
387         );
388         MatcherAssert.assertThat(smart.publicRepos(), Matchers.is(value));
389     }
390 
391     /**
392      * Tests if a User.Smart object handles public_gists JSON property.
393      * @throws Exception if any problem occurs.
394      */
395     @Test
396     public void hasPublicGists() throws Exception {
397         final int value = Tv.FOUR;
398         final User.Smart smart = this.userWith(
399             "public_gists",
400             String.valueOf(value)
401         );
402         MatcherAssert.assertThat(smart.publicGists(), Matchers.is(value));
403     }
404 
405     /**
406      * Tests if a User.Smart object handles followers JSON property.
407      * @throws Exception if any problem occurs.
408      */
409     @Test
410     public void hasFollowersCount() throws Exception {
411         final int value = Tv.FIVE;
412         final User.Smart smart = this.userWith(
413             "followers",
414             String.valueOf(value)
415         );
416         MatcherAssert.assertThat(smart.followersCount(), Matchers.is(value));
417     }
418 
419     /**
420      * Tests if a User.Smart object handles following JSON property.
421      * @throws Exception if any problem occurs.
422      */
423     @Test
424     public void hasFollowingCount() throws Exception {
425         final int value = Tv.SIX;
426         final User.Smart smart = this.userWith(
427             "following",
428             String.valueOf(value)
429         );
430         MatcherAssert.assertThat(smart.followingCount(), Matchers.is(value));
431     }
432 
433     /**
434      * Tests if a User.Smart object handles created_at JSON property.
435      * @throws Exception if any problem occurs.
436      */
437     @Test
438     public void hasCreated() throws Exception {
439         final Github.Time value = new Github.Time("2014-07-04T15:29:43Z");
440         final User.Smart smart = this.userWith("created_at", value.toString());
441         MatcherAssert.assertThat(smart.created(), Matchers.is(value));
442     }
443 
444     /**
445      * Tests if a User.Smart object handles updated_at JSON property.
446      * @throws Exception if any problem occurs.
447      */
448     @Test
449     public void hasUpdated() throws Exception {
450         final Github.Time value = new Github.Time("2014-07-04T15:29:43Z");
451         final User.Smart smart = this.userWith("updated_at", value.toString());
452         MatcherAssert.assertThat(smart.updated(), Matchers.is(value));
453     }
454 
455     /**
456      * Verifies the behaviour of the RtUser.notifications method.
457      * @throws Exception Thrown in case of error.
458      */
459     @Test
460     public void notifications() throws Exception {
461         MatcherAssert.assertThat(
462             new RtUser(
463                 new MkGithub(),
464                 new FakeRequest()
465             ).notifications(),
466             Matchers.not(Matchers.nullValue())
467         );
468     }
469 
470     /**
471      * Method 'markAsRead()' should complete successfully if response code is
472      * 205.
473      * @throws Exception Thrown in case of error.
474      */
475     @Test
476     public void markAsReadOkIfResponseStatusIs205() throws Exception {
477         MkContainer container = null;
478         try {
479             container = new MkGrizzlyContainer().next(
480                 new MkAnswer.Simple(HttpURLConnection.HTTP_RESET)
481             ).start(this.resource.port());
482             final Request req = new ApacheRequest(container.home());
483             final Github github = Mockito.mock(Github.class);
484             Mockito.when(github.entry()).thenReturn(req);
485             new RtUser(
486                 github,
487                 req
488             ).markAsRead(new Date());
489         } finally {
490             container.close();
491         }
492     }
493 
494     /**
495      * Method 'markAsRead()' should fail if response code is not 205.
496      * @throws Exception Thrown in case of an error other than the
497      *  AssertionError.
498      */
499     @Test(expected = AssertionError.class)
500     public void markAsReadErrorIfResponseStatusIsNot205() throws Exception {
501         MkContainer container = null;
502         try {
503             container = new MkGrizzlyContainer().next(
504                 new MkAnswer.Simple(HttpURLConnection.HTTP_INTERNAL_ERROR)
505             ).start(this.resource.port());
506             final Request req = new ApacheRequest(container.home());
507             final Github github = Mockito.mock(Github.class);
508             Mockito.when(github.entry()).thenReturn(req);
509             new RtUser(
510                 github,
511                 req
512             ).markAsRead(new Date());
513         } finally {
514             container.close();
515         }
516     }
517 
518     /**
519      * Return User.Smart with given property.
520      * @param property The propery as specified at https://developer.github.com/v3/users/#get-a-single-user
521      * @param value The property value
522      * @return User.Smart with given property.
523      */
524     private User.Smart userWith(final String property, final String value) {
525         return new User.Smart(
526             new RtUser(
527                 Mockito.mock(Github.class),
528                 new FakeRequest().withBody(
529                     Json.createObjectBuilder()
530                         .add(property, value)
531                         .build()
532                         .toString()
533                 ),
534                 "octoc"
535             )
536         );
537     }
538 }