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.mock;
31  
32  import com.jcabi.github.Coordinates;
33  import com.jcabi.github.Event;
34  import com.jcabi.github.Github;
35  import com.jcabi.github.Issue;
36  import com.jcabi.github.Label;
37  import com.jcabi.github.Repo;
38  import java.util.Collections;
39  import java.util.Iterator;
40  import org.hamcrest.CustomMatcher;
41  import org.hamcrest.MatcherAssert;
42  import org.hamcrest.Matchers;
43  import org.junit.Test;
44  import org.mockito.Mockito;
45  
46  /**
47   * Test case for {@link MkIssue}.
48   * @author Yegor Bugayenko (yegor256@gmail.com)
49   * @version $Id: 0104e6a480f0a871bd2f2ee20fc657bf45b08b33 $
50   * @checkstyle MultipleStringLiterals (500 lines)
51   * @checkstyle ClassDataAbstractionCouplingCheck (500 lines)
52   */
53  @SuppressWarnings("PMD.TooManyMethods")
54  public final class MkIssueTest {
55  
56      /**
57       * MkIssue can open and close.
58       * @throws Exception If some problem inside
59       */
60      @Test
61      public void opensAndCloses() throws Exception {
62          final Issue issue = this.issue();
63          MatcherAssert.assertThat(
64              new Issue.Smart(issue).isOpen(),
65              Matchers.is(true)
66          );
67          new Issue.Smart(issue).close();
68          MatcherAssert.assertThat(
69              new Issue.Smart(issue).isOpen(),
70              Matchers.is(false)
71          );
72      }
73  
74      /**
75       * MkIssue can point to an absent pull request.
76       * @throws Exception If some problem inside
77       */
78      @Test
79      public void pointsToAnEmptyPullRequest() throws Exception {
80          final Issue issue = this.issue();
81          MatcherAssert.assertThat(
82              new Issue.Smart(issue).isPull(),
83              Matchers.is(false)
84          );
85      }
86  
87      /**
88       * MkIssue can show an issue author.
89       * @throws Exception If some problem inside
90       */
91      @Test
92      public void showsIssueAuthor() throws Exception {
93          final Issue issue = this.issue();
94          MatcherAssert.assertThat(
95              new Issue.Smart(issue).author().login(),
96              Matchers.notNullValue()
97          );
98      }
99  
100     /**
101      * MkIssue can change title.
102      * @throws Exception If some problem inside
103      */
104     @Test
105     public void changesTitle() throws Exception {
106         final Issue issue = this.issue();
107         new Issue.Smart(issue).title("hey, works?");
108         MatcherAssert.assertThat(
109             new Issue.Smart(issue).title(),
110             Matchers.startsWith("hey, ")
111         );
112     }
113 
114     /**
115      * MkIssue can change body.
116      * @throws Exception If some problem inside
117      */
118     @Test
119     public void changesBody() throws Exception {
120         final Issue issue = this.issue();
121         new Issue.Smart(issue).body("hey, body works?");
122         MatcherAssert.assertThat(
123             new Issue.Smart(issue).body(),
124             Matchers.startsWith("hey, b")
125         );
126     }
127 
128     /**
129      * MkIssue can expose all properties.
130      * @throws Exception If some problem inside
131      */
132     @Test
133     public void exponsesProperties() throws Exception {
134         final Issue.Smart issue = new Issue.Smart(this.issue());
135         MatcherAssert.assertThat(issue.createdAt(), Matchers.notNullValue());
136         MatcherAssert.assertThat(issue.updatedAt(), Matchers.notNullValue());
137         MatcherAssert.assertThat(issue.htmlUrl(), Matchers.notNullValue());
138     }
139 
140     /**
141      * MkIssue can list its labels.
142      * @throws Exception If some problem inside
143      */
144     @Test
145     public void listsReadOnlyLabels() throws Exception {
146         final Issue issue = this.issue();
147         final String tag = "test-tag";
148         issue.repo().labels().create(tag, "c0c0c0");
149         issue.labels().add(Collections.singletonList(tag));
150         MatcherAssert.assertThat(
151             new Issue.Smart(issue).roLabels().iterate(),
152             Matchers.<Label>hasItem(
153                 new CustomMatcher<Label>("label just created") {
154                     @Override
155                     public boolean matches(final Object item) {
156                         return Label.class.cast(item).name().equals(tag);
157                     }
158                 }
159             )
160         );
161     }
162 
163     /**
164      * MkIssue should be able to compare different instances.
165      * @throws Exception when a problem occurs.
166      */
167     @Test
168     public void canCompareInstances() throws Exception {
169         final MkIssue less = new MkIssue(
170             new MkStorage.InFile(),
171             "login-less",
172             Mockito.mock(Coordinates.class),
173             1
174         );
175         final MkIssue greater = new MkIssue(
176             new MkStorage.InFile(),
177             "login-greater",
178             Mockito.mock(Coordinates.class),
179             2
180         );
181         MatcherAssert.assertThat(
182             less.compareTo(greater),
183             Matchers.lessThan(0)
184         );
185         MatcherAssert.assertThat(
186             greater.compareTo(less),
187             Matchers.greaterThan(0)
188         );
189     }
190 
191     /**
192      * MkIssue can remember it's author.
193      * @throws Exception when a problem occurs.
194      */
195     @Test
196     public void canRememberItsAuthor() throws Exception {
197         final MkGithub first = new MkGithub("first");
198         final Github second = first.relogin("second");
199         final Repo repo = first.randomRepo();
200         final int number = second.repos()
201             .get(repo.coordinates())
202             .issues()
203             .create("", "")
204             .number();
205         final Issue issue = first.repos()
206             .get(repo.coordinates())
207             .issues()
208             .get(number);
209         MatcherAssert.assertThat(
210             new Issue.Smart(issue).author().login(),
211             Matchers.is("second")
212         );
213     }
214 
215     /**
216      * Can check if issue exists.
217      * @throws Exception if any error occurs.
218      */
219     @Test
220     public void canCheckIfIssueExists() throws Exception {
221         MatcherAssert.assertThat(this.issue().exists(), Matchers.is(true));
222     }
223 
224     /**
225      * MkIssue.exists() return false on nonexistent issues.
226      * @throws Exception if any error occurs.
227      */
228     @Test
229     public void canCheckNonExistentIssue() throws Exception {
230         MatcherAssert.assertThat(
231             new MkIssue(
232                 new MkStorage.InFile(),
233                 "login",
234                 new Coordinates.Simple("user", "repo"),
235                 1
236             ).exists(),
237             Matchers.is(false)
238         );
239     }
240 
241     /**
242      * MkIssue can assign a user.
243      * @throws Exception If some problem inside
244      */
245     @Test
246     public void assignsUser() throws Exception {
247         final Issue.Smart issue = new Issue.Smart(this.issue());
248         issue.assign("walter");
249         MatcherAssert.assertThat(
250             issue.assignee().login(),
251             Matchers.startsWith("wal")
252         );
253     }
254 
255     /**
256      * MkIssue can create a closed event when closing an issue.
257      * @throws Exception If some problem inside
258      */
259     @Test
260     public void createsClosedEvent() throws Exception {
261         final Issue.Smart issue = new Issue.Smart(this.issue());
262         issue.close();
263         MatcherAssert.assertThat(
264             issue.events(),
265             Matchers.<Event>iterableWithSize(1)
266         );
267         final Event.Smart closed = new Event.Smart(
268             issue.events().iterator().next()
269         );
270         MatcherAssert.assertThat(
271             closed.type(),
272             Matchers.equalTo(Event.CLOSED)
273         );
274     }
275 
276     /**
277      * MkIssue can create a reopened event when closing an issue.
278      * @throws Exception If some problem inside
279      */
280     @Test
281     public void createsReopenedEvent() throws Exception {
282         final Issue.Smart issue = new Issue.Smart(this.issue());
283         issue.close();
284         issue.open();
285         MatcherAssert.assertThat(
286             issue.events(),
287             Matchers.<Event>iterableWithSize(2)
288         );
289         final Iterator<Event> events = issue.events().iterator();
290         final Event.Smart closed = new Event.Smart(events.next());
291         final Event.Smart reopened = new Event.Smart(events.next());
292         MatcherAssert.assertThat(
293             closed.type(),
294             Matchers.equalTo(Event.CLOSED)
295         );
296         MatcherAssert.assertThat(
297             reopened.type(),
298             Matchers.equalTo(Event.REOPENED)
299         );
300     }
301 
302     /**
303      * Create an issue to work with.
304      * @return Issue just created
305      * @throws Exception If some problem inside
306      */
307     private Issue issue() throws Exception {
308         return new MkGithub().randomRepo()
309             .issues().create("hey", "how are you?");
310     }
311 
312 }