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;
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: 5855198722fcb91258dbce9f5f0a1f2098f46643 $
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      public transient ExpectedException thrown = ExpectedException.none();
91  
92      /**
93       * The rule for skipping test if there's BindException.
94       * @checkstyle VisibilityModifierCheck (3 lines)
95       */
96      @Rule
97      public final transient RandomPort resource = new RandomPort();
98  
99      /**
100      * RtPublicMembers can fetch its organization.
101      * @throws IOException If there is an I/O problem
102      */
103     @Test
104     public void fetchesOrg() throws IOException {
105         final Organization org = organization();
106         MatcherAssert.assertThat(
107             new RtPublicMembers(new FakeRequest(), org).org(),
108             Matchers.equalTo(org)
109         );
110     }
111 
112     /**
113      * RtPublicMembers can conceal a user's membership in the organization.
114      * @throws IOException If there is an I/O problem
115      */
116     @Test
117     public void concealsMembers() throws IOException {
118         try (
119             final MkContainer container = new MkGrizzlyContainer()
120             .next(new MkAnswer.Simple(HttpURLConnection.HTTP_NO_CONTENT))
121             .next(new MkAnswer.Simple(HttpURLConnection.HTTP_INTERNAL_ERROR))
122             .start(this.resource.port())
123         ) {
124             final RtPublicMembers members = new RtPublicMembers(
125                 new ApacheRequest(container.home()),
126                 organization()
127             );
128             members.conceal(user());
129             final MkQuery req = container.take();
130             MatcherAssert.assertThat(
131                 req.method(),
132                 Matchers.equalTo(Request.DELETE)
133             );
134             MatcherAssert.assertThat(
135                 req.body(),
136                 Matchers.isEmptyOrNullString()
137             );
138             MatcherAssert.assertThat(
139                 req.uri().toString(),
140                 Matchers.endsWith(MEMBER_URL)
141             );
142             this.thrown.expect(AssertionError.class);
143             members.conceal(user());
144             container.stop();
145         }
146     }
147 
148     /**
149      * RtPublicMembers can publicize the membership of
150      * a user in the organization.
151      * @throws IOException If there is an I/O problem
152      */
153     @Test
154     public void publicizesMembers() throws IOException {
155         try (MkContainer container = new MkGrizzlyContainer()
156             .next(new MkAnswer.Simple(HttpURLConnection.HTTP_NO_CONTENT))
157             .next(new MkAnswer.Simple(HttpURLConnection.HTTP_INTERNAL_ERROR))
158             .start(this.resource.port())
159         ) {
160             final RtPublicMembers members = new RtPublicMembers(
161                 new ApacheRequest(container.home()),
162                 organization()
163             );
164             members.publicize(user());
165             final MkQuery req = container.take();
166             MatcherAssert.assertThat(
167                 req.method(),
168                 Matchers.equalTo(Request.PUT)
169             );
170             MatcherAssert.assertThat(
171                 req.uri().toString(),
172                 Matchers.endsWith(MEMBER_URL)
173             );
174             this.thrown.expect(AssertionError.class);
175             members.publicize(user());
176             container.stop();
177         }
178     }
179 
180     /**
181      * RtPublicMembers can check whether a user
182      * is a public member of the organization.
183      * @throws IOException If there is an I/O problem
184      */
185     @Test
186     public void checkPublicMembership() throws IOException {
187         try (
188             final MkContainer container = new MkGrizzlyContainer()
189                 .next(new MkAnswer.Simple(HttpURLConnection.HTTP_NOT_FOUND))
190                 .next(new MkAnswer.Simple(HttpURLConnection.HTTP_NOT_FOUND))
191                 .next(new MkAnswer.Simple(HttpURLConnection.HTTP_NO_CONTENT))
192                 .next(
193                     new MkAnswer.Simple(HttpURLConnection.HTTP_INTERNAL_ERROR)
194                 )
195                 .start(this.resource.port())
196         ) {
197             final RtPublicMembers members = new RtPublicMembers(
198                 new ApacheRequest(container.home()),
199                 organization()
200             );
201             members.contains(user());
202             final MkQuery req = container.take();
203             MatcherAssert.assertThat(
204                 req.method(),
205                 Matchers.equalTo(Request.GET)
206             );
207             MatcherAssert.assertThat(
208                 req.uri().toString(),
209                 Matchers.endsWith(MEMBER_URL)
210             );
211             MatcherAssert.assertThat(
212                 "404 is interpreted as the user not being a public member",
213                 !members.contains(user())
214             );
215             MatcherAssert.assertThat(
216                 "204 is interpreted as the user being a public member",
217                 members.contains(user())
218             );
219             this.thrown.expect(AssertionError.class);
220             members.contains(user());
221             container.stop();
222         }
223     }
224 
225     /**
226      * RtPublicMembers can list the public members of the organization.
227      * @throws IOException If there is an I/O problem
228      */
229     @Test
230     public void iteratesPublicMembers() throws IOException {
231         try (
232             final MkContainer container = new MkGrizzlyContainer()
233                 .next(
234                     new MkAnswer.Simple(
235                         HttpURLConnection.HTTP_OK,
236                         "[{\"login\":\"octobat\"}]"
237                     )
238             )
239             .next(new MkAnswer.Simple(HttpURLConnection.HTTP_INTERNAL_ERROR))
240             .start(this.resource.port())
241         ) {
242             final RtPublicMembers members = new RtPublicMembers(
243                 new ApacheRequest(container.home()),
244                 organization()
245             );
246             members.iterate().iterator().next();
247             final MkQuery req = container.take();
248             MatcherAssert.assertThat(
249                 req.method(),
250                 Matchers.equalTo(Request.GET)
251             );
252             MatcherAssert.assertThat(
253                 req.uri().toString(),
254                 Matchers.endsWith(MEMBERS_URL)
255             );
256             this.thrown.expect(AssertionError.class);
257             members.iterate().iterator().next();
258             container.stop();
259         }
260     }
261 
262     /**
263      * Get test organization.
264      * @return Organization
265      * @throws IOException If there is an I/O problem
266      */
267     private static Organization organization() throws IOException {
268         return new MkOrganization(new MkStorage.InFile(), ORG);
269     }
270 
271     /**
272      * Get test user.
273      * @return User
274      * @throws IOException If there is an I/O problem
275      */
276     private static User user() throws IOException {
277         return new MkGithub().users().get(USERNAME);
278     }
279 }