-
+
Configure SMTP now to enable account onboarding and recovery.
+
SMTP is active.
+
Draft saved.
+
Test passed.
+
+
+
-
-
-
- Defer SMTP
-
+
+
diff --git a/src/test/java/com/lab/labtimesheet/feature/account/controller/BootstrapOnboardingWebIntegrationTest.java b/src/test/java/com/lab/labtimesheet/feature/account/controller/BootstrapOnboardingWebIntegrationTest.java
index 49de963..a37d169 100644
--- a/src/test/java/com/lab/labtimesheet/feature/account/controller/BootstrapOnboardingWebIntegrationTest.java
+++ b/src/test/java/com/lab/labtimesheet/feature/account/controller/BootstrapOnboardingWebIntegrationTest.java
@@ -71,6 +71,8 @@ class BootstrapOnboardingWebIntegrationTest {
.with(user("admin@example.com").roles("ADMIN")))
.andExpect(status().isOk())
.andExpect(view().name("smtp/defer"))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("/assets/theme.js")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("data-sidebar-toggle")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("Account onboarding is disabled")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("Back")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("Configure SMTP")))
@@ -91,6 +93,20 @@ class BootstrapOnboardingWebIntegrationTest {
.with(csrf()))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrl("/dashboard"));
+
+ mockMvc.perform(get("/dashboard")
+ .with(user("admin@example.com").roles("ADMIN")))
+ .andExpect(status().isOk())
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "This installation remains restricted until tested SMTP is active.")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("href=\"/admin/smtp\"")));
+
+ mockMvc.perform(get("/admin/accounts/new")
+ .with(user("admin@example.com").roles("ADMIN")))
+ .andExpect(status().isOk())
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "This installation remains restricted until tested SMTP is active.")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("href=\"/admin/smtp\"")));
}
@Test
diff --git a/src/test/java/com/lab/labtimesheet/feature/integration/controller/SmtpOnboardingWebIntegrationTest.java b/src/test/java/com/lab/labtimesheet/feature/integration/controller/SmtpOnboardingWebIntegrationTest.java
index 607b318..7aae0a6 100644
--- a/src/test/java/com/lab/labtimesheet/feature/integration/controller/SmtpOnboardingWebIntegrationTest.java
+++ b/src/test/java/com/lab/labtimesheet/feature/integration/controller/SmtpOnboardingWebIntegrationTest.java
@@ -102,6 +102,11 @@ class SmtpOnboardingWebIntegrationTest {
.andExpect(content().string(org.hamcrest.Matchers.containsString("SMTP is active")))
.andExpect(content().string(org.hamcrest.Matchers.not(
org.hamcrest.Matchers.containsString("restricted installation"))));
+
+ mockMvc.perform(get("/admin/accounts/new").with(user("admin@example.com").roles("ADMIN")))
+ .andExpect(status().isOk())
+ .andExpect(content().string(org.hamcrest.Matchers.not(
+ org.hamcrest.Matchers.containsString("installation remains restricted"))));
}
@Test
@@ -111,16 +116,71 @@ class SmtpOnboardingWebIntegrationTest {
.with(csrf())
.param("host", "")
.param("port", "70000")
- .param("securityMode", "STARTTLS")
+ .param("securityMode", "")
.param("username", "smtp-user")
- .param("password", "must-not-be-rendered")
+ .param("password", "")
.param("fromAddress", "not-an-email")
- .param("fromName", "Safe sender name"))
+ .param("fromName", ""))
.andExpect(status().isOk())
.andExpect(view().name("smtp/form"))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("/assets/theme.js")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-form-error-summary\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "aria-labelledby=\"smtp-form-error-summary-title\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-host\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "aria-describedby=\"smtp-host-error\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-host-error\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-port\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "aria-describedby=\"smtp-port-error\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-port-error\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-security-mode\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "aria-describedby=\"smtp-security-mode-error\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "id=\"smtp-security-mode-error\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-username\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-password\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "aria-describedby=\"smtp-authentication-error\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "id=\"smtp-username\" autocomplete=\"username\" aria-invalid=\"true\""
+ + " aria-describedby=\"smtp-authentication-error\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "id=\"smtp-authentication-error\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-from-address\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "aria-describedby=\"smtp-from-address-error\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "id=\"smtp-from-address-error\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-from-name\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "aria-describedby=\"smtp-from-name-error\"")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "id=\"smtp-from-name-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("Host is required")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("Port must be between")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("valid email address")))
+ .andExpect(content().string(org.hamcrest.Matchers.not(
+ org.hamcrest.Matchers.containsString("value=\"smtp-secret\""))));
+ }
+
+ @Test
+ void invalidDraftRetainsSafeValuesButNeverTheSubmittedPassword() throws Exception {
+ mockMvc.perform(post("/admin/smtp/draft")
+ .with(user("admin@example.com").roles("ADMIN"))
+ .with(csrf())
+ .param("host", "")
+ .param("port", "1025")
+ .param("securityMode", "NONE")
+ .param("username", "safe-smtp-user")
+ .param("password", "must-not-be-rendered")
+ .param("fromAddress", "notifications@example.com")
+ .param("fromName", "Safe sender name"))
+ .andExpect(status().isOk())
+ .andExpect(view().name("smtp/form"))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("safe-smtp-user")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("Safe sender name")))
.andExpect(content().string(org.hamcrest.Matchers.not(
org.hamcrest.Matchers.containsString("must-not-be-rendered"))));
@@ -130,7 +190,8 @@ class SmtpOnboardingWebIntegrationTest {
void restrictedWarningPersistsOnAdminPagesUntilActivationAndMutationsRequireCsrf() throws Exception {
mockMvc.perform(get("/admin/accounts/new").with(user("admin@example.com").roles("ADMIN")))
.andExpect(status().isOk())
- .andExpect(content().string(org.hamcrest.Matchers.containsString("restricted installation")));
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "installation remains restricted")));
mockMvc.perform(post("/admin/smtp/draft")
.with(user("admin@example.com").roles("ADMIN"))
diff --git a/src/test/java/com/lab/labtimesheet/feature/reporting/controller/DashboardControllerWebTest.java b/src/test/java/com/lab/labtimesheet/feature/reporting/controller/DashboardControllerWebTest.java
index bc5176c..39b5329 100644
--- a/src/test/java/com/lab/labtimesheet/feature/reporting/controller/DashboardControllerWebTest.java
+++ b/src/test/java/com/lab/labtimesheet/feature/reporting/controller/DashboardControllerWebTest.java
@@ -6,6 +6,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
@@ -35,15 +36,31 @@ class DashboardControllerWebTest {
void adminRendersAdminDashboardForAuthenticatedIdentity() throws Exception {
var dashboard = new DashboardView.Admin(2, 1, 1, 3);
given(dashboards.admin("admin@example.test")).willReturn(dashboard);
+ given(smtpConfiguration.hasActiveConfiguration()).willReturn(false);
mvc.perform(get("/dashboard").with(user("admin@example.test").roles("ADMIN")))
.andExpect(status().isOk())
.andExpect(view().name("dashboard/admin"))
- .andExpect(model().attribute("dashboard", dashboard));
+ .andExpect(model().attribute("dashboard", dashboard))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString(
+ "This installation remains restricted until tested SMTP is active.")))
+ .andExpect(content().string(org.hamcrest.Matchers.containsString("href=\"/admin/smtp\"")));
verify(dashboards).admin("admin@example.test");
}
+ @Test
+ void activeSmtpKeepsAdminDashboardFreeOfTheRestrictedInstallationWarning() throws Exception {
+ var dashboard = new DashboardView.Admin(2, 1, 1, 3);
+ given(dashboards.admin("admin@example.test")).willReturn(dashboard);
+ given(smtpConfiguration.hasActiveConfiguration()).willReturn(true);
+
+ mvc.perform(get("/dashboard").with(user("admin@example.test").roles("ADMIN")))
+ .andExpect(status().isOk())
+ .andExpect(content().string(org.hamcrest.Matchers.not(org.hamcrest.Matchers.containsString(
+ "This installation remains restricted until tested SMTP is active."))));
+ }
+
@Test
void mentorRendersMentorDashboardForAuthenticatedIdentity() throws Exception {
var dashboard = new DashboardView.Mentor("Mentor", 2, 4, 1);
@@ -52,7 +69,9 @@ class DashboardControllerWebTest {
mvc.perform(get("/dashboard").with(user("mentor@example.test").roles("MENTOR")))
.andExpect(status().isOk())
.andExpect(view().name("dashboard/mentor"))
- .andExpect(model().attribute("dashboard", dashboard));
+ .andExpect(model().attribute("dashboard", dashboard))
+ .andExpect(content().string(org.hamcrest.Matchers.not(org.hamcrest.Matchers.containsString(
+ "This installation remains restricted until tested SMTP is active."))));
verify(dashboards).mentor("mentor@example.test");
}