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.github.mock.MkGithub;
33  import com.jcabi.github.mock.MkOrganization;
34  import com.jcabi.github.mock.MkStorage;
35  import com.jcabi.http.Request;
36  import com.jcabi.http.mock.MkAnswer;
37  import com.jcabi.http.mock.MkContainer;
38  import com.jcabi.http.mock.MkGrizzlyContainer;
39  import com.jcabi.http.mock.MkQuery;
40  import com.jcabi.http.request.ApacheRequest;
41  import com.jcabi.http.request.FakeRequest;
42  import java.io.IOException;
43  import java.net.HttpURLConnection;
44  import org.hamcrest.MatcherAssert;
45  import org.hamcrest.Matchers;
46  import org.junit.Rule;
47  import org.junit.Test;
48  import org.junit.rules.ExpectedException;
49  
50  /**
51   * Test case for {@link RtPublicMembers}.
52   *
53   * @author Chris Rebert (github@chrisrebert.com)
54   * @version $Id: b8dbac492d4e73dffab16bad5893b7a631a7ac9c $
55   * @checkstyle ClassDataAbstractionCouplingCheck (500 lines)
56   */
57  public final class RtPublicMembersTest {
58      /**
59       * Test organization.
60       */
61      private static final String ORG = "starfleet";
62  
63      /**
64       * Test username.
65       */
66      private static final String USERNAME = "wesley";
67  
68      /**
69       * Public members URL for test org.
70       */
71      private static final String MEMBERS_URL = String.format(
72          "/orgs/%s/public_members",
73          ORG
74      );
75  
76      /**
77       * Public member URL for test user in test org.
78       */
79      private static final String MEMBER_URL = String.format(
80          "%s/%s",
81          MEMBERS_URL,
82          USERNAME
83      );
84  
85      /**
86       * Rule for checking thrown exception.
87       * @checkstyle VisibilityModifier (3 lines)
88       */
89      @Rule
90      @SuppressWarnings("deprecation")
91      public transient ExpectedException thrown = ExpectedException.none();
92  
93      /**
94       * The rule for skipping test if there's BindException.
95       * @checkstyle VisibilityModifierCheck (3 lines)
96       */
97      @Rule
98      public final transient RandomPort resource = new RandomPort();
99  
100     /**
101      * RtPublicMembers can fetch its organization.
102      * @throws IOException If there is an I/O problem
103      */
104     @Test
105     public void fetchesOrg() throws IOException {
106         final Organization org = organization();
107         MatcherAssert.assertThat(
108             new RtPublicMembers(new FakeRequest(), org).org(),
109             Matchers.equalTo(org)
110         );
111     }
112 
113     /**
114      * RtPublicMembers can conceal a user's membership in the organization.
115      * @throws IOException If there is an I/O problem
116      */
117     @Test
118     public void concealsMembers() throws IOException {
119         try (
120             final MkContainer container = new MkGrizzlyContainer()
121             .next(new MkAnswer.Simple(HttpURLConnection.HTTP_NO_CONTENT))
122             .next(new MkAnswer.Simple(HttpURLConnection.HTTP_INTERNAL_ERROR))
123             .start(this.resource.port())
124         ) {
125             final RtPublicMembers members = new RtPublicMembers(
126                 new ApacheRequest(container.home()),
127                 organization()
128             );
129             members.conceal(user());
130             final MkQuery req = container.take();
131             MatcherAssert.assertThat(
132                 req.method(),
133                 Matchers.equalTo(Request.DELETE)
134             );
135             MatcherAssert.assertThat(
136                 req.body(),
137                 Matchers.is(Matchers.emptyOrNullString())
138             );
139             MatcherAssert.assertThat(
140                 req.uri().toString(),
141                 Matchers.endsWith(MEMBER_URL)
142             );
143             this.thrown.expect(AssertionError.class);
144             members.conceal(user());
145             container.stop();
146         }
147     }
148 
149     /**
150      * RtPublicMembers can publicize the membership of
151      * a user in the organization.
152      * @throws IOException If there is an I/O problem
153      */
154     @Test
155     public void publicizesMembers() throws IOException {
156         try (MkContainer container = new MkGrizzlyContainer()
157             .next(new MkAnswer.Simple(HttpURLConnection.HTTP_NO_CONTENT))
158             .next(new MkAnswer.Simple(HttpURLConnection.HTTP_INTERNAL_ERROR))
159             .start(this.resource.port())
160         ) {
161             final RtPublicMembers members = new RtPublicMembers(
162                 new ApacheRequest(container.home()),
163                 organization()
164             );
165             members.publicize(user());
166             final MkQuery req = container.take();
167             MatcherAssert.assertThat(
168                 req.method(),
169                 Matchers.equalTo(Request.PUT)
170             );
171             MatcherAssert.assertThat(
172                 req.uri().toString(),
173                 Matchers.endsWith(MEMBER_URL)
174             );
175             this.thrown.expect(AssertionError.class);
176             members.publicize(user());
177             container.stop();
178         }
179     }
180 
181     /**
182      * RtPublicMembers can check whether a user
183      * is a public member of the organization.
184      * @throws IOException If there is an I/O problem
185      */
186     @Test
187     public void checkPublicMembership() throws IOException {
188         try (
189             final MkContainer container = new MkGrizzlyContainer()
190                 .next(new MkAnswer.Simple(HttpURLConnection.HTTP_NOT_FOUND))
191                 .next(new MkAnswer.Simple(HttpURLConnection.HTTP_NOT_FOUND))
192                 .next(new MkAnswer.Simple(HttpURLConnection.HTTP_NO_CONTENT))
193                 .next(
194                     new MkAnswer.Simple(HttpURLConnection.HTTP_INTERNAL_ERROR)
195                 )
196                 .start(this.resource.port())
197         ) {
198             final RtPublicMembers members = new RtPublicMembers(
199                 new ApacheRequest(container.home()),
200                 organization()
201             );
202             members.contains(user());
203             final MkQuery req = container.take();
204             MatcherAssert.assertThat(
205                 req.method(),
206                 Matchers.equalTo(Request.GET)
207             );
208             MatcherAssert.assertThat(
209                 req.uri().toString(),
210                 Matchers.endsWith(MEMBER_URL)
211             );
212             MatcherAssert.assertThat(
213                 "404 is interpreted as the user not being a public member",
214                 !members.contains(user())
215             );
216             MatcherAssert.assertThat(
217                 "204 is interpreted as the user being a public member",
218                 members.contains(user())
219             );
220             this.thrown.expect(AssertionError.class);
221             members.contains(user());
222             container.stop();
223         }
224     }
225 
226     /**
227      * RtPublicMembers can list the public members of the organization.
228      * @throws IOException If there is an I/O problem
229      */
230     @Test
231     public void iteratesPublicMembers() throws IOException {
232         try (
233             final MkContainer container = new MkGrizzlyContainer()
234                 .next(
235                     new MkAnswer.Simple(
236                         HttpURLConnection.HTTP_OK,
237                         "[{\"login\":\"octobat\"}]"
238                     )
239             )
240             .next(new MkAnswer.Simple(HttpURLConnection.HTTP_INTERNAL_ERROR))
241             .start(this.resource.port())
242         ) {
243             final RtPublicMembers members = new RtPublicMembers(
244                 new ApacheRequest(container.home()),
245                 organization()
246             );
247             members.iterate().iterator().next();
248             final MkQuery req = container.take();
249             MatcherAssert.assertThat(
250                 req.method(),
251                 Matchers.equalTo(Request.GET)
252             );
253             MatcherAssert.assertThat(
254                 req.uri().toString(),
255                 Matchers.endsWith(MEMBERS_URL)
256             );
257             this.thrown.expect(AssertionError.class);
258             members.iterate().iterator().next();
259             container.stop();
260         }
261     }
262 
263     /**
264      * Get test organization.
265      * @return Organization
266      * @throws IOException If there is an I/O problem
267      */
268     private static Organization organization() throws IOException {
269         return new MkOrganization(new MkStorage.InFile(), ORG);
270     }
271 
272     /**
273      * Get test user.
274      * @return User
275      * @throws IOException If there is an I/O problem
276      */
277     private static User user() throws IOException {
278         return new MkGithub().users().get(USERNAME);
279     }
280 }