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.github.mock.MkGitHub;
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.request.ApacheRequest;
13  import com.jcabi.http.request.FakeRequest;
14  import jakarta.json.Json;
15  import java.io.IOException;
16  import java.net.HttpURLConnection;
17  import java.text.ParseException;
18  import java.util.Date;
19  import org.hamcrest.MatcherAssert;
20  import org.hamcrest.Matchers;
21  import org.junit.jupiter.api.Assertions;
22  import org.junit.jupiter.api.Test;
23  import org.junit.jupiter.api.extension.ExtendWith;
24  import org.mockito.Mockito;
25  
26  /**
27   * Test case for {@link RtUser}.
28   * @since 0.1
29   * @checkstyle MultipleStringLiterals (500 lines)
30   * @checkstyle ClassDataAbstractionCouplingCheck (500 lines)
31   * @checkstyle LineLengthCheck (500 lines)
32   * @checkstyle MagicNumberCheck (500 lines)
33   * @checkstyle MethodNameCheck (500 lines)
34   */
35  @SuppressWarnings({"PMD.AvoidDuplicateLiterals", "PMD.TooManyMethods" })
36  @ExtendWith(RandomPort.class)
37  final class RtUserTest {
38  
39      /**
40       * The rule for skipping test if there's BindException.
41       * @checkstyle VisibilityModifierCheck (3 lines)
42       */
43      @Test
44      void checksWhoAmI() throws IOException {
45          final String login = "monalia";
46          final RtUser user = new RtUser(
47              Mockito.mock(GitHub.class),
48              new FakeRequest().withBody(
49                  Json.createObjectBuilder()
50                      .add("login", login)
51                      .build().toString()
52              )
53          );
54          MatcherAssert.assertThat(
55              "Values are not equal",
56              user.login(),
57              Matchers.equalTo(login)
58          );
59      }
60  
61      @Test
62      void checksIfHeHasAName() throws IOException {
63          final User.Smart smart = new User.Smart(
64              new RtUser(
65                  Mockito.mock(GitHub.class),
66                  new FakeRequest().withBody(
67                      Json.createObjectBuilder()
68                          .add("name", "octoc")
69                          .build()
70                          .toString()
71                  ),
72                  "octoc"
73              )
74          );
75          MatcherAssert.assertThat(
76              "Values are not equal",
77              smart.hasName(),
78              Matchers.equalTo(true)
79          );
80      }
81  
82      @Test
83      void checksIfHeHasNoName() throws IOException {
84          final User.Smart smart = new User.Smart(
85              new RtUser(
86                  Mockito.mock(GitHub.class),
87                  new FakeRequest().withBody(
88                      Json.createObjectBuilder()
89                          .build()
90                          .toString()
91                  ),
92                  "octoc"
93              )
94          );
95          MatcherAssert.assertThat(
96              "Values are not equal",
97              smart.hasName(),
98              Matchers.equalTo(false)
99          );
100     }
101 
102     @Test
103     void describeAsJson() throws IOException {
104         final RtUser user = new RtUser(
105             Mockito.mock(GitHub.class),
106             new FakeRequest().withBody(
107                 Json.createObjectBuilder()
108                     .add("name", "monalisa")
109                     .add("email", "octocat@github.com")
110                     .build()
111                     .toString()
112             ),
113             "octoc"
114         );
115         MatcherAssert.assertThat(
116             "Values are not equal",
117             user.json().toString(),
118             Matchers.equalTo(
119                 "{\"name\":\"monalisa\",\"email\":\"octocat@github.com\"}"
120             )
121         );
122     }
123 
124     @Test
125     void executePatchRequest() throws IOException {
126         final MkContainer container = new MkGrizzlyContainer().next(
127             new MkAnswer.Simple(
128                 HttpURLConnection.HTTP_OK,
129                 "{\"login\":\"octocate\"}"
130             )
131         ).start(RandomPort.port());
132         final RtUser json = new RtUser(
133             Mockito.mock(GitHub.class),
134             new ApacheRequest(container.home())
135         );
136         json.patch(
137             Json.createObjectBuilder()
138                 .add("location", "San Francisco")
139                 .build()
140         );
141         MatcherAssert.assertThat(
142             "Values are not equal",
143             container.take().method(),
144             Matchers.equalTo(Request.PATCH)
145         );
146         container.stop();
147     }
148 
149     @Test
150     void fetchesEmails() {
151         final GitHub github = Mockito.mock(GitHub.class);
152         Mockito.when(github.entry()).thenReturn(new FakeRequest());
153         final User user = new RtUser(github, new FakeRequest());
154         MatcherAssert.assertThat(
155             "Value is null", user.emails(), Matchers.notNullValue()
156         );
157     }
158 
159     @Test
160     void fetchesOrganizations() {
161         final GitHub github = Mockito.mock(GitHub.class);
162         Mockito.when(github.entry()).thenReturn(new FakeRequest());
163         final User user = new RtUser(github, new FakeRequest());
164         MatcherAssert.assertThat(
165             "Value is null", user.organizations(), Matchers.notNullValue()
166         );
167     }
168 
169     @Test
170     void hasHtmlUrl() throws IOException {
171         final String value = "http://github.example.com";
172         final User.Smart smart = RtUserTest.userWith("html_url", value);
173         MatcherAssert.assertThat(
174             "Values are not equal", smart.htmlUrl(), Matchers.is(value)
175         );
176     }
177 
178     @Test
179     void hasFollowersUrl() throws IOException {
180         final String value = "http://github.example.com/followers";
181         final User.Smart smart = RtUserTest.userWith("followers_url", value);
182         MatcherAssert.assertThat(
183             "Values are not equal", smart.followersUrl(), Matchers.is(value)
184         );
185     }
186 
187     @Test
188     void hasFollowingUrl() throws IOException {
189         final String value = "http://github.example.com/following";
190         final User.Smart smart = RtUserTest.userWith("following_url", value);
191         MatcherAssert.assertThat(
192             "Values are not equal", smart.followingUrl(), Matchers.is(value)
193         );
194     }
195 
196     @Test
197     void hasGistsUrl() throws IOException {
198         final String value = "http://github.example.com/gists";
199         final User.Smart smart = RtUserTest.userWith("gists_url", value);
200         MatcherAssert.assertThat(
201             "Values are not equal", smart.gistsUrl(), Matchers.is(value)
202         );
203     }
204 
205     @Test
206     void hasStarredUrl() throws IOException {
207         final String value = "http://github.example.com/starred";
208         final User.Smart smart = RtUserTest.userWith("starred_url", value);
209         MatcherAssert.assertThat(
210             "Values are not equal", smart.starredUrl(), Matchers.is(value)
211         );
212     }
213 
214     @Test
215     void hasSubscriptionsUrl() throws IOException {
216         final String value = "http://github.example.com/subscriptions";
217         final User.Smart smart = RtUserTest.userWith("subscriptions_url", value);
218         MatcherAssert.assertThat(
219             "Values are not equal", smart.subscriptionsUrl(), Matchers.is(value)
220         );
221     }
222 
223     @Test
224     void hasOrganizationsUrl() throws IOException {
225         final String value = "http://github.example.com/organizations";
226         final User.Smart smart = RtUserTest.userWith("organizations_url", value);
227         MatcherAssert.assertThat(
228             "Values are not equal", smart.organizationsUrl(), Matchers.is(value)
229         );
230     }
231 
232     @Test
233     void hasReposUrl() throws IOException {
234         final String value = "http://github.example.com/repos";
235         final User.Smart smart = RtUserTest.userWith("repos_url", value);
236         MatcherAssert.assertThat(
237             "Values are not equal", smart.reposUrl(), Matchers.is(value)
238         );
239     }
240 
241     @Test
242     void hasEventsUrl() throws IOException {
243         final String value = "http://github.example.com/events";
244         final User.Smart smart = RtUserTest.userWith("events_url", value);
245         MatcherAssert.assertThat(
246             "Values are not equal", smart.eventsUrl(), Matchers.is(value)
247         );
248     }
249 
250     @Test
251     void hasReceivedEventsUrl() throws IOException {
252         final String value = "http://github.example.com/received_events";
253         final User.Smart smart = RtUserTest.userWith("received_events_url", value);
254         MatcherAssert.assertThat(
255             "Values are not equal", smart.receivedEventsUrl(), Matchers.is(value)
256         );
257     }
258 
259     @Test
260     void hasType() throws IOException {
261         final String value = "http://github.example.com/organizations";
262         final User.Smart smart = RtUserTest.userWith("type", value);
263         MatcherAssert.assertThat(
264             "Values are not equal", smart.type(), Matchers.is(value)
265         );
266     }
267 
268     @Test
269     void hasSiteAdmin() throws IOException {
270         final User.Smart smart = RtUserTest.userWith("site_admin", "true");
271         MatcherAssert.assertThat(
272             "Values are not equal", smart.siteAdmin(), Matchers.is(true)
273         );
274     }
275 
276     @Test
277     void hasBlog() throws IOException {
278         final String value = "http://blog.example.com";
279         final User.Smart smart = RtUserTest.userWith("blog", value);
280         MatcherAssert.assertThat(
281             "Values are not equal", smart.blog(), Matchers.is(value)
282         );
283     }
284 
285     @Test
286     void hasHireable() throws IOException {
287         final User.Smart smart = RtUserTest.userWith("hireable", "true");
288         MatcherAssert.assertThat(
289             "Values are not equal", smart.hireable(), Matchers.is(true)
290         );
291     }
292 
293     @Test
294     void hasBio() throws IOException {
295         final String value = "http://github.example.com/bio";
296         final User.Smart smart = RtUserTest.userWith("bio", value);
297         MatcherAssert.assertThat(
298             "Values are not equal", smart.bio(), Matchers.is(value)
299         );
300     }
301 
302     @Test
303     void hasPublicRepos() throws IOException {
304         final int value = 3;
305         final User.Smart smart = RtUserTest.userWith(
306             "public_repos",
307             String.valueOf(value)
308         );
309         MatcherAssert.assertThat(
310             "Values are not equal", smart.publicRepos(), Matchers.is(value)
311         );
312     }
313 
314     @Test
315     void hasPublicGists() throws IOException {
316         final int value = 4;
317         final User.Smart smart = RtUserTest.userWith(
318             "public_gists",
319             String.valueOf(value)
320         );
321         MatcherAssert.assertThat(
322             "Values are not equal", smart.publicGists(), Matchers.is(value)
323         );
324     }
325 
326     @Test
327     void hasFollowersCount() throws IOException {
328         final int value = 5;
329         final User.Smart smart = RtUserTest.userWith(
330             "followers",
331             String.valueOf(value)
332         );
333         MatcherAssert.assertThat(
334             "Values are not equal", smart.followersCount(), Matchers.is(value)
335         );
336     }
337 
338     @Test
339     void hasFollowingCount() throws IOException {
340         final int value = 6;
341         final User.Smart smart = RtUserTest.userWith(
342             "following",
343             String.valueOf(value)
344         );
345         MatcherAssert.assertThat(
346             "Values are not equal", smart.followingCount(), Matchers.is(value)
347         );
348     }
349 
350     @Test
351     void hasCreated() throws ParseException, IOException {
352         final GitHub.Time value = new GitHub.Time("2014-07-04T15:29:43Z");
353         final User.Smart smart = RtUserTest.userWith("created_at", value.toString());
354         MatcherAssert.assertThat(
355             "Values are not equal", smart.created().toString(), Matchers.is(value.toString())
356         );
357     }
358 
359     @Test
360     void hasUpdated() throws ParseException, IOException {
361         final GitHub.Time value = new GitHub.Time("2014-07-04T15:29:43Z");
362         final User.Smart smart = RtUserTest.userWith("updated_at", value.toString());
363         MatcherAssert.assertThat(
364             "Values are not equal", smart.updated().toString(), Matchers.is(value.toString())
365         );
366     }
367 
368     @Test
369     void notifications() throws IOException {
370         MatcherAssert.assertThat(
371             "Value is not null",
372             new RtUser(
373                 new MkGitHub(),
374                 new FakeRequest()
375             ).notifications(),
376             Matchers.not(Matchers.nullValue())
377         );
378     }
379 
380     /**
381      * Method 'markAsRead()' should complete successfully if response code is
382      * 205.
383      */
384     @Test
385     void markAsReadOkIfResponseStatusIs205() throws IOException {
386         MkContainer container = null;
387         try {
388             container = new MkGrizzlyContainer().next(
389                 new MkAnswer.Simple(HttpURLConnection.HTTP_RESET)
390             ).start(RandomPort.port());
391             final Request req = new ApacheRequest(container.home());
392             final GitHub github = Mockito.mock(GitHub.class);
393             Mockito.when(github.entry()).thenReturn(req);
394             new RtUser(
395                 github,
396                 req
397             ).markAsRead(new Date());
398         } finally {
399             if (container != null) {
400                 container.close();
401             }
402         }
403     }
404 
405     @Test
406     void markAsReadErrorIfResponseStatusIsNot205() throws IOException {
407         final MkContainer container = new MkGrizzlyContainer().next(
408             new MkAnswer.Simple(HttpURLConnection.HTTP_INTERNAL_ERROR)
409         ).start(RandomPort.port());
410         try {
411             final Request req = new ApacheRequest(container.home());
412             final GitHub github = Mockito.mock(GitHub.class);
413             Mockito.when(github.entry()).thenReturn(req);
414             final RtUser user = new RtUser(github, req);
415             Assertions.assertThrows(
416                 AssertionError.class,
417                 () -> user.markAsRead(new Date()),
418                 "Should throw when response status is not 205"
419             );
420         } finally {
421             container.close();
422         }
423     }
424 
425     /**
426      * Return User.Smart with given property.
427      * @param property The property as specified at https://developer.github.com/v3/users/#get-a-single-user
428      * @param value The property value
429      * @return User.Smart with given property.
430      */
431     private static User.Smart userWith(final String property, final String value) {
432         return new User.Smart(
433             new RtUser(
434                 Mockito.mock(GitHub.class),
435                 new FakeRequest().withBody(
436                     Json.createObjectBuilder()
437                         .add(property, value)
438                         .build()
439                         .toString()
440                 ),
441                 "octoc"
442             )
443         );
444     }
445 }