Skip to content

Commit c1f9af8

Browse files
committed
feat: Add comprehensive tests for AdministrativeMonitor snooze functionality and enhance snooze duration input UI.
1 parent 0cbfea5 commit c1f9af8

File tree

5 files changed

+144
-3
lines changed

5 files changed

+144
-3
lines changed

core/src/main/resources/hudson/model/Messages.properties

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,3 +427,8 @@ ManagementLink.Category.UNCATEGORIZED=Uncategorized
427427
FileParameterValue.IndexTitle=File Parameters
428428

429429
UserPreferencesProperty.DisplayName=Preferences
430+
431+
Snooze=Snooze
432+
Snooze.duration.label=Snooze duration in minutes
433+
Snooze.duration.placeholder=Minutes
434+
Snooze.duration.title=Enter duration in minutes (max 525600 = 1 year)

core/src/main/resources/jenkins/diagnostics/ControllerExecutorsAgents/message.jelly

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ THE SOFTWARE.
3838
<input type="hidden" name="${h.crumbRequestField}" value="${h.getCrumb(request)}"/>
3939
</j:if>
4040
<input type="hidden" name="duration" value="custom"/>
41-
<input type="number" name="customMinutes" placeholder="Minutes" min="1" style="width: 80px;" class="jenkins-input" required="required"/>
41+
<label for="snooze-minutes-${it.id}" class="jenkins-visually-hidden">${%Snooze.duration.label}</label>
42+
<input type="number" id="snooze-minutes-${it.id}" name="customMinutes" placeholder="${%Snooze.duration.placeholder}" min="1" max="525600" step="1" style="width: 80px;" class="jenkins-input" required="required" aria-label="${%Snooze.duration.label}" title="${%Snooze.duration.title}"/>
4243
<f:submit value="${%Snooze}"/>
4344
</form>
4445
</div>

core/src/main/resources/jenkins/diagnostics/ControllerExecutorsNoAgents/message.jelly

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ THE SOFTWARE.
3939
<input type="hidden" name="${h.crumbRequestField}" value="${h.getCrumb(request)}"/>
4040
</j:if>
4141
<input type="hidden" name="duration" value="custom"/>
42-
<input type="number" name="customMinutes" placeholder="Minutes" min="1" style="width: 80px;" class="jenkins-input" required="required"/>
42+
<label for="snooze-minutes-${it.id}" class="jenkins-visually-hidden">${%Snooze.duration.label}</label>
43+
<input type="number" id="snooze-minutes-${it.id}" name="customMinutes" placeholder="${%Snooze.duration.placeholder}" min="1" max="525600" step="1" style="width: 80px;" class="jenkins-input" required="required" aria-label="${%Snooze.duration.label}" title="${%Snooze.duration.title}"/>
4344
<f:submit value="${%Snooze}"/>
4445
</form>
4546
</div>

core/src/main/resources/jenkins/model/BuiltInNodeMigration/message.jelly

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
<input type="hidden" name="${h.crumbRequestField}" value="${h.getCrumb(request)}"/>
1515
</j:if>
1616
<input type="hidden" name="duration" value="custom"/>
17-
<input type="number" name="customMinutes" placeholder="Minutes" min="1" style="width: 80px;" class="jenkins-input" required="required"/>
17+
<label for="snooze-minutes-${it.id}" class="jenkins-visually-hidden">${%Snooze.duration.label}</label>
18+
<input type="number" id="snooze-minutes-${it.id}" name="customMinutes" placeholder="${%Snooze.duration.placeholder}" min="1" max="525600" step="1" style="width: 80px;" class="jenkins-input" required="required" aria-label="${%Snooze.duration.label}" title="${%Snooze.duration.title}"/>
1819
<f:submit value="${%Snooze}"/>
1920
</form>
2021
</div>
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package hudson.model;
2+
3+
import static org.junit.jupiter.api.Assertions.assertFalse;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
5+
import static org.junit.jupiter.api.Assertions.assertTrue;
6+
import static org.mockito.Mockito.mock;
7+
import static org.mockito.Mockito.mockStatic;
8+
import static org.mockito.Mockito.verify;
9+
import static org.mockito.Mockito.when;
10+
11+
import java.io.IOException;
12+
import java.util.HashMap;
13+
import java.util.HashSet;
14+
import java.util.Map;
15+
import java.util.Set;
16+
import jenkins.model.Jenkins;
17+
import org.junit.jupiter.api.AfterEach;
18+
import org.junit.jupiter.api.BeforeEach;
19+
import org.junit.jupiter.api.Test;
20+
import org.mockito.MockedStatic;
21+
22+
class AdministrativeMonitorTest {
23+
24+
private MockedStatic<Jenkins> mockedJenkins;
25+
private Jenkins jenkins;
26+
private Map<String, Long> snoozedMonitors;
27+
private Set<String> disabledMonitors;
28+
29+
@BeforeEach
30+
void setUp() {
31+
mockedJenkins = mockStatic(Jenkins.class);
32+
jenkins = mock(Jenkins.class);
33+
mockedJenkins.when(Jenkins::get).thenReturn(jenkins);
34+
35+
snoozedMonitors = new HashMap<>();
36+
disabledMonitors = new HashSet<>();
37+
38+
when(jenkins.getSnoozedAdministrativeMonitors()).thenReturn(snoozedMonitors);
39+
when(jenkins.getDisabledAdministrativeMonitors()).thenReturn(disabledMonitors);
40+
}
41+
42+
@AfterEach
43+
void tearDown() {
44+
mockedJenkins.close();
45+
}
46+
47+
private static class TestMonitor extends AdministrativeMonitor {
48+
TestMonitor(String id) {
49+
super(id);
50+
}
51+
52+
@Override
53+
public boolean isActivated() {
54+
return true;
55+
}
56+
}
57+
58+
@Test
59+
void testSnoozeExpiry() throws IOException, InterruptedException {
60+
TestMonitor monitor = new TestMonitor("test-monitor");
61+
long duration = 100L; // 100ms
62+
monitor.snooze(duration);
63+
64+
assertTrue(monitor.isSnoozed(), "Monitor should be snoozed immediately");
65+
assertFalse(monitor.isEnabled(), "Monitor should not be enabled while snoozed");
66+
67+
Thread.sleep(150); // Wait for expiry
68+
69+
assertFalse(monitor.isSnoozed(), "Monitor should not be snoozed after expiry");
70+
}
71+
72+
@Test
73+
void testCleanupRemovesOnlyThisMonitor() throws IOException {
74+
TestMonitor monitor1 = new TestMonitor("monitor-1");
75+
TestMonitor monitor2 = new TestMonitor("monitor-2");
76+
77+
// Snooze both, expire monitor1
78+
snoozedMonitors.put("monitor-1", System.currentTimeMillis() - 1000);
79+
snoozedMonitors.put("monitor-2", System.currentTimeMillis() + 10000);
80+
81+
monitor1.isSnoozed(); // Should trigger cleanup for monitor1
82+
83+
assertFalse(snoozedMonitors.containsKey("monitor-1"), "Expired monitor should be removed");
84+
assertTrue(snoozedMonitors.containsKey("monitor-2"), "Active monitor should remain");
85+
}
86+
87+
@Test
88+
void testSnoozePersistence() throws IOException {
89+
TestMonitor monitor = new TestMonitor("persist-monitor");
90+
monitor.snooze(10000);
91+
92+
assertTrue(snoozedMonitors.containsKey("persist-monitor"), "Snooze map should contain the monitor ID");
93+
verify(jenkins).save(); // Verify persistence was called
94+
}
95+
96+
@Test
97+
void testMultipleMonitorsIndependent() throws IOException {
98+
TestMonitor monitor1 = new TestMonitor("m1");
99+
TestMonitor monitor2 = new TestMonitor("m2");
100+
101+
monitor1.snooze(10000);
102+
103+
assertTrue(monitor1.isSnoozed());
104+
assertFalse(monitor2.isSnoozed());
105+
}
106+
107+
@Test
108+
void testNegativeDuration() {
109+
TestMonitor monitor = new TestMonitor("negative");
110+
assertThrows(IllegalArgumentException.class, () -> monitor.snooze(-1));
111+
}
112+
113+
@Test
114+
void testZeroDuration() {
115+
TestMonitor monitor = new TestMonitor("zero");
116+
assertThrows(IllegalArgumentException.class, () -> monitor.snooze(0));
117+
}
118+
119+
@Test
120+
void testExcessiveDuration() {
121+
TestMonitor monitor = new TestMonitor("excessive");
122+
long tooLong = 365L * 24 * 60 * 60 * 1000 + 1;
123+
assertThrows(IllegalArgumentException.class, () -> monitor.snooze(tooLong));
124+
}
125+
126+
@Test
127+
void testMaxDurationAllowed() throws IOException {
128+
TestMonitor monitor = new TestMonitor("max");
129+
long maxDuration = 365L * 24 * 60 * 60 * 1000;
130+
monitor.snooze(maxDuration);
131+
assertTrue(monitor.isSnoozed());
132+
}
133+
}

0 commit comments

Comments
 (0)