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.google.common.base.Optional;
33 import com.jcabi.aspects.Tv;
34 import com.jcabi.github.Event;
35 import java.util.Iterator;
36 import org.hamcrest.MatcherAssert;
37 import org.hamcrest.Matchers;
38 import org.junit.Test;
39
40 /**
41 * Test case for {@link MkIssueEvents}.
42 * @author Chris Rebert (github@chrisrebert.com)
43 * @version $Id: f8b453ae08480a2fc14c1621adecc58a16a60d42 $
44 * @since 0.23
45 */
46 public final class MkIssueEventsTest {
47 /**
48 * Absent optional string.
49 */
50 private static final Optional<String> ABSENT_STR = Optional.absent();
51
52 /**
53 * MkIssueEvents can create issue events.
54 * @throws Exception If some problem inside
55 */
56 @Test
57 public void createsIssueEvent() throws Exception {
58 final MkIssueEvents events = this.issueEvents();
59 final String login = "jack";
60 final String type = "locked";
61 final long before = MkIssueEventsTest.now();
62 final Event.Smart event = new Event.Smart(
63 events.create(
64 type,
65 2,
66 login,
67 MkIssueEventsTest.ABSENT_STR
68 )
69 );
70 final long after = MkIssueEventsTest.now();
71 MatcherAssert.assertThat(
72 event.type(),
73 Matchers.equalTo(type)
74 );
75 MatcherAssert.assertThat(
76 event.author().login(),
77 Matchers.equalTo(login)
78 );
79 MatcherAssert.assertThat(
80 event.url().toString(),
81 Matchers.equalTo(
82 String.format(
83 // @checkstyle LineLength (1 line)
84 "https://api.jcabi-github.invalid/repos/jeff/%s/issues/events/1",
85 events.repo().coordinates().repo()
86 )
87 )
88 );
89 MatcherAssert.assertThat(
90 event.createdAt().getTime(),
91 Matchers.greaterThanOrEqualTo(before)
92 );
93 MatcherAssert.assertThat(
94 event.createdAt().getTime(),
95 Matchers.lessThanOrEqualTo(after)
96 );
97 }
98
99 /**
100 * MkIssueEvents can create an issue event with a label attribute.
101 * @throws Exception If some problem inside
102 */
103 @Test
104 public void createsIssueEventWithLabel() throws Exception {
105 final MkIssueEvents events = this.issueEvents();
106 final String label = "my label";
107 final Event.Smart event = new Event.Smart(
108 events.create(
109 "labeled",
110 2,
111 "samuel",
112 Optional.of(label)
113 )
114 );
115 MatcherAssert.assertThat(
116 event.label().get().name(),
117 Matchers.equalTo(label)
118 );
119 }
120
121 /**
122 * MkIssueEvents can get a single issue event.
123 * @throws Exception If some problem inside
124 */
125 @Test
126 public void getsIssueEvent() throws Exception {
127 final MkIssueEvents events = this.issueEvents();
128 final String type = "unlocked";
129 final String login = "jill";
130 final int eventnum = events.create(
131 type,
132 2,
133 login,
134 MkIssueEventsTest.ABSENT_STR
135 ).number();
136 final Event.Smart event = new Event.Smart(events.get(eventnum));
137 MatcherAssert.assertThat(
138 event.number(),
139 Matchers.equalTo(eventnum)
140 );
141 MatcherAssert.assertThat(
142 event.type(),
143 Matchers.equalTo(type)
144 );
145 MatcherAssert.assertThat(
146 event.author().login(),
147 Matchers.equalTo(login)
148 );
149 }
150
151 /**
152 * MkIssueEvents can iterate over issue events in correct order.
153 * @throws Exception If some problem inside
154 */
155 @Test
156 public void iteratesIssueEvents() throws Exception {
157 final MkIssueEvents events = this.issueEvents();
158 final Event first = events.create(
159 "closed",
160 3,
161 "john",
162 MkIssueEventsTest.ABSENT_STR
163 );
164 final Event second = events.create(
165 "reopened",
166 3,
167 "jane",
168 MkIssueEventsTest.ABSENT_STR
169 );
170 MatcherAssert.assertThat(
171 events.iterate(),
172 Matchers.<Event>iterableWithSize(2)
173 );
174 final Iterator<Event> iter = events.iterate().iterator();
175 MatcherAssert.assertThat(
176 iter.next(),
177 Matchers.equalTo(first)
178 );
179 MatcherAssert.assertThat(
180 iter.next(),
181 Matchers.equalTo(second)
182 );
183 }
184
185 /**
186 * Create an MkIssueEvents to work with.
187 * Can't use normal IssueEvents because we need the mock-only
188 * {@link MkIssueEvents#create(String, int, String, Optional)} method.
189 * @return MkIssueEvents
190 * @throws Exception If some problem inside
191 */
192 private MkIssueEvents issueEvents() throws Exception {
193 return MkIssueEvents.class.cast(
194 new MkGithub().randomRepo().issueEvents()
195 );
196 }
197
198 /**
199 * Obtains the current time.
200 * @return Current time (in milliseconds since epoch) truncated to the nearest second
201 */
202 private static long now() {
203 final long sinceepoch = System.currentTimeMillis();
204 return sinceepoch - sinceepoch % Tv.THOUSAND;
205 }
206 }