Render default UIs using lightweight templates
This commit is contained in:
committed by
Rob Winch
parent
a953a3d162
commit
8d47906191
@@ -67,140 +67,142 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
@ExtendWith(SpringTestContextExtension.class)
|
||||
public class DefaultLoginPageConfigurerTests {
|
||||
|
||||
//@formatter:off
|
||||
public static final String EXPECTED_HTML_HEAD = " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <style>\n"
|
||||
+ " /* General layout */\n"
|
||||
+ " body {\n"
|
||||
+ " font-family: system-ui, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n"
|
||||
+ " background-color: #eee;\n"
|
||||
+ " padding: 40px 0;\n"
|
||||
+ " margin: 0;\n"
|
||||
+ " line-height: 1.5;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " h2 {\n"
|
||||
+ " margin-top: 0;\n"
|
||||
+ " margin-bottom: 0.5rem;\n"
|
||||
+ " font-size: 2rem;\n"
|
||||
+ " font-weight: 500;\n"
|
||||
+ " line-height: 2rem;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " .content {\n"
|
||||
+ " margin-right: auto;\n"
|
||||
+ " margin-left: auto;\n"
|
||||
+ " padding-right: 15px;\n"
|
||||
+ " padding-left: 15px;\n"
|
||||
+ " width: 100%;\n"
|
||||
+ " box-sizing: border-box;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " @media (min-width: 800px) {\n"
|
||||
+ " .content {\n"
|
||||
+ " max-width: 760px;\n"
|
||||
+ " }\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " /* Components */\n"
|
||||
+ " a,\n"
|
||||
+ " a:visited {\n"
|
||||
+ " text-decoration: none;\n"
|
||||
+ " color: #06f;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " a:hover {\n"
|
||||
+ " text-decoration: underline;\n"
|
||||
+ " color: #003c97;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " input[type=\"text\"],\n"
|
||||
+ " input[type=\"password\"] {\n"
|
||||
+ " height: auto;\n"
|
||||
+ " width: 100%;\n"
|
||||
+ " font-size: 1rem;\n"
|
||||
+ " padding: 0.5rem;\n"
|
||||
+ " box-sizing: border-box;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " button {\n"
|
||||
+ " padding: 0.5rem 1rem;\n"
|
||||
+ " font-size: 1.25rem;\n"
|
||||
+ " line-height: 1.5;\n"
|
||||
+ " border: none;\n"
|
||||
+ " border-radius: 0.1rem;\n"
|
||||
+ " width: 100%;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " button.primary {\n"
|
||||
+ " color: #fff;\n"
|
||||
+ " background-color: #06f;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " .alert {\n"
|
||||
+ " padding: 0.75rem 1rem;\n"
|
||||
+ " margin-bottom: 1rem;\n"
|
||||
+ " line-height: 1.5;\n"
|
||||
+ " border-radius: 0.1rem;\n"
|
||||
+ " width: 100%;\n"
|
||||
+ " box-sizing: border-box;\n"
|
||||
+ " border-width: 1px;\n"
|
||||
+ " border-style: solid;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " .alert.alert-danger {\n"
|
||||
+ " color: #6b1922;\n"
|
||||
+ " background-color: #f7d5d7;\n"
|
||||
+ " border-color: #eab6bb;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " .alert.alert-success {\n"
|
||||
+ " color: #145222;\n"
|
||||
+ " background-color: #d1f0d9;\n"
|
||||
+ " border-color: #c2ebcb;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " .screenreader {\n"
|
||||
+ " position: absolute;\n"
|
||||
+ " clip: rect(0 0 0 0);\n"
|
||||
+ " height: 1px;\n"
|
||||
+ " width: 1px;\n"
|
||||
+ " padding: 0;\n"
|
||||
+ " border: 0;\n"
|
||||
+ " overflow: hidden;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " table {\n"
|
||||
+ " width: 100%;\n"
|
||||
+ " max-width: 100%;\n"
|
||||
+ " margin-bottom: 2rem;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " .table-striped tr:nth-of-type(2n + 1) {\n"
|
||||
+ " background-color: #e1e1e1;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " td {\n"
|
||||
+ " padding: 0.75rem;\n"
|
||||
+ " vertical-align: top;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " /* Login / logout layouts */\n"
|
||||
+ " .login-form,\n"
|
||||
+ " .logout-form {\n"
|
||||
+ " max-width: 340px;\n"
|
||||
+ " padding: 0 15px 15px 15px;\n"
|
||||
+ " margin: 0 auto 2rem auto;\n"
|
||||
+ " box-sizing: border-box;\n"
|
||||
+ " }\n"
|
||||
+ " </style>\n"
|
||||
+ " </head>\n";
|
||||
//@formatter:on
|
||||
public static final String EXPECTED_HTML_HEAD = """
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<title>Please sign in</title>
|
||||
<style>
|
||||
/* General layout */
|
||||
body {
|
||||
font-family: system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
background-color: #eee;
|
||||
padding: 40px 0;
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
\s\s\s\s
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 2rem;
|
||||
font-weight: 500;
|
||||
line-height: 2rem;
|
||||
}
|
||||
\s\s\s\s
|
||||
.content {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
\s\s\s\s
|
||||
@media (min-width: 800px) {
|
||||
.content {
|
||||
max-width: 760px;
|
||||
}
|
||||
}
|
||||
\s\s\s\s
|
||||
/* Components */
|
||||
a,
|
||||
a:visited {
|
||||
text-decoration: none;
|
||||
color: #06f;
|
||||
}
|
||||
\s\s\s\s
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
color: #003c97;
|
||||
}
|
||||
\s\s\s\s
|
||||
input[type="text"],
|
||||
input[type="password"] {
|
||||
height: auto;
|
||||
width: 100%;
|
||||
font-size: 1rem;
|
||||
padding: 0.5rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
\s\s\s\s
|
||||
button {
|
||||
padding: 0.5rem 1rem;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.5;
|
||||
border: none;
|
||||
border-radius: 0.1rem;
|
||||
width: 100%;
|
||||
}
|
||||
\s\s\s\s
|
||||
button.primary {
|
||||
color: #fff;
|
||||
background-color: #06f;
|
||||
}
|
||||
\s\s\s\s
|
||||
.alert {
|
||||
padding: 0.75rem 1rem;
|
||||
margin-bottom: 1rem;
|
||||
line-height: 1.5;
|
||||
border-radius: 0.1rem;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
}
|
||||
\s\s\s\s
|
||||
.alert.alert-danger {
|
||||
color: #6b1922;
|
||||
background-color: #f7d5d7;
|
||||
border-color: #eab6bb;
|
||||
}
|
||||
\s\s\s\s
|
||||
.alert.alert-success {
|
||||
color: #145222;
|
||||
background-color: #d1f0d9;
|
||||
border-color: #c2ebcb;
|
||||
}
|
||||
\s\s\s\s
|
||||
.screenreader {
|
||||
position: absolute;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
\s\s\s\s
|
||||
table {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
\s\s\s\s
|
||||
.table-striped tr:nth-of-type(2n + 1) {
|
||||
background-color: #e1e1e1;
|
||||
}
|
||||
\s\s\s\s
|
||||
td {
|
||||
padding: 0.75rem;
|
||||
vertical-align: top;
|
||||
}
|
||||
\s\s\s\s
|
||||
/* Login / logout layouts */
|
||||
.login-form,
|
||||
.logout-form {
|
||||
max-width: 340px;
|
||||
padding: 0 15px 15px 15px;
|
||||
margin: 0 auto 2rem auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
""";
|
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this);
|
||||
|
||||
@@ -222,26 +224,32 @@ public class DefaultLoginPageConfigurerTests {
|
||||
this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect((result) -> {
|
||||
CsrfToken token = (CsrfToken) result.getRequest().getAttribute(CsrfToken.class.getName());
|
||||
assertThat(result.getResponse().getContentAsString()).isEqualTo("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ EXPECTED_HTML_HEAD
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"content\">\n"
|
||||
+ " <form class=\"login-form\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2>Please sign in</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"screenreader\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"screenreader\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ "<input name=\"" + token.getParameterName() + "\" type=\"hidden\" value=\"" + token.getToken() + "\" />\n"
|
||||
+ " <button type=\"submit\" class=\"primary\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>");
|
||||
assertThat(result.getResponse().getContentAsString()).isEqualTo(
|
||||
EXPECTED_HTML_HEAD +
|
||||
"""
|
||||
<body>
|
||||
<div class="content">
|
||||
<form class="login-form" method="post" action="/login">
|
||||
<h2>Please sign in</h2>
|
||||
\s
|
||||
<p>
|
||||
<label for="username" class="screenreader">Username</label>
|
||||
<input type="text" id="username" name="username" placeholder="Username" required autofocus>
|
||||
</p>
|
||||
<p>
|
||||
<label for="password" class="screenreader">Password</label>
|
||||
<input type="password" id="password" name="password" placeholder="Password" required>
|
||||
</p>
|
||||
|
||||
<input name="_csrf" type="hidden" value="%s" />
|
||||
<button type="submit" class="primary">Sign in</button>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>""".formatted(token.getToken()));
|
||||
});
|
||||
// @formatter:on
|
||||
}
|
||||
@@ -263,25 +271,32 @@ public class DefaultLoginPageConfigurerTests {
|
||||
.sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect((result) -> {
|
||||
CsrfToken token = (CsrfToken) result.getRequest().getAttribute(CsrfToken.class.getName());
|
||||
assertThat(result.getResponse().getContentAsString()).isEqualTo("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ EXPECTED_HTML_HEAD
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"content\">\n"
|
||||
+ " <form class=\"login-form\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2>Please sign in</h2>\n"
|
||||
+ "<div class=\"alert alert-danger\" role=\"alert\">Bad credentials</div> <p>\n"
|
||||
+ " <label for=\"username\" class=\"screenreader\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n" + " <p>\n"
|
||||
+ " <label for=\"password\" class=\"screenreader\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ "<input name=\"" + token.getParameterName() + "\" type=\"hidden\" value=\"" + token.getToken() + "\" />\n"
|
||||
+ " <button type=\"submit\" class=\"primary\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>");
|
||||
assertThat(result.getResponse().getContentAsString()).isEqualTo(
|
||||
EXPECTED_HTML_HEAD +
|
||||
"""
|
||||
<body>
|
||||
<div class="content">
|
||||
<form class="login-form" method="post" action="/login">
|
||||
<h2>Please sign in</h2>
|
||||
<div class="alert alert-danger" role="alert">Bad credentials</div>
|
||||
<p>
|
||||
<label for="username" class="screenreader">Username</label>
|
||||
<input type="text" id="username" name="username" placeholder="Username" required autofocus>
|
||||
</p>
|
||||
<p>
|
||||
<label for="password" class="screenreader">Password</label>
|
||||
<input type="password" id="password" name="password" placeholder="Password" required>
|
||||
</p>
|
||||
|
||||
<input name="_csrf" type="hidden" value="%s" />
|
||||
<button type="submit" class="primary">Sign in</button>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>""".formatted(token.getToken()));
|
||||
});
|
||||
// @formatter:on
|
||||
}
|
||||
@@ -307,26 +322,32 @@ public class DefaultLoginPageConfigurerTests {
|
||||
this.mvc.perform(get("/login?logout").sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect((result) -> {
|
||||
CsrfToken token = (CsrfToken) result.getRequest().getAttribute(CsrfToken.class.getName());
|
||||
assertThat(result.getResponse().getContentAsString()).isEqualTo("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ EXPECTED_HTML_HEAD
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"content\">\n"
|
||||
+ " <form class=\"login-form\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2>Please sign in</h2>\n"
|
||||
+ "<div class=\"alert alert-success\" role=\"alert\">You have been signed out</div> <p>\n"
|
||||
+ " <label for=\"username\" class=\"screenreader\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"screenreader\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ "<input name=\"" + token.getParameterName() + "\" type=\"hidden\" value=\"" + token.getToken() + "\" />\n"
|
||||
+ " <button type=\"submit\" class=\"primary\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>");
|
||||
assertThat(result.getResponse().getContentAsString()).isEqualTo(
|
||||
EXPECTED_HTML_HEAD +
|
||||
"""
|
||||
<body>
|
||||
<div class="content">
|
||||
<form class="login-form" method="post" action="/login">
|
||||
<h2>Please sign in</h2>
|
||||
<div class="alert alert-success" role="alert">You have been signed out</div>
|
||||
<p>
|
||||
<label for="username" class="screenreader">Username</label>
|
||||
<input type="text" id="username" name="username" placeholder="Username" required autofocus>
|
||||
</p>
|
||||
<p>
|
||||
<label for="password" class="screenreader">Password</label>
|
||||
<input type="password" id="password" name="password" placeholder="Password" required>
|
||||
</p>
|
||||
|
||||
<input name="_csrf" type="hidden" value="%s" />
|
||||
<button type="submit" class="primary">Sign in</button>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>""".formatted(token.getToken()));
|
||||
});
|
||||
// @formatter:on
|
||||
}
|
||||
@@ -352,27 +373,32 @@ public class DefaultLoginPageConfigurerTests {
|
||||
this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect((result) -> {
|
||||
CsrfToken token = (CsrfToken) result.getRequest().getAttribute(CsrfToken.class.getName());
|
||||
assertThat(result.getResponse().getContentAsString()).isEqualTo("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ EXPECTED_HTML_HEAD
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"content\">\n"
|
||||
+ " <form class=\"login-form\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2>Please sign in</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"screenreader\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"screenreader\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ "<p><input type='checkbox' name='remember-me'/> Remember me on this computer.</p>\n"
|
||||
+ "<input name=\"" + token.getParameterName() + "\" type=\"hidden\" value=\"" + token.getToken() + "\" />\n"
|
||||
+ " <button type=\"submit\" class=\"primary\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>");
|
||||
assertThat(result.getResponse().getContentAsString()).isEqualTo(
|
||||
EXPECTED_HTML_HEAD +
|
||||
"""
|
||||
<body>
|
||||
<div class="content">
|
||||
<form class="login-form" method="post" action="/login">
|
||||
<h2>Please sign in</h2>
|
||||
\s
|
||||
<p>
|
||||
<label for="username" class="screenreader">Username</label>
|
||||
<input type="text" id="username" name="username" placeholder="Username" required autofocus>
|
||||
</p>
|
||||
<p>
|
||||
<label for="password" class="screenreader">Password</label>
|
||||
<input type="password" id="password" name="password" placeholder="Password" required>
|
||||
</p>
|
||||
<p><input type='checkbox' name='remember-me'/> Remember me on this computer.</p>
|
||||
<input name="_csrf" type="hidden" value="%s" />
|
||||
<button type="submit" class="primary">Sign in</button>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>""".formatted(token.getToken()));
|
||||
});
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@@ -45,140 +45,142 @@ public class FormLoginBeanDefinitionParserTests {
|
||||
|
||||
private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/FormLoginBeanDefinitionParserTests";
|
||||
|
||||
//@formatter:off
|
||||
public static final String EXPECTED_HTML_HEAD = " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <style>\n"
|
||||
+ " /* General layout */\n"
|
||||
+ " body {\n"
|
||||
+ " font-family: system-ui, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n"
|
||||
+ " background-color: #eee;\n"
|
||||
+ " padding: 40px 0;\n"
|
||||
+ " margin: 0;\n"
|
||||
+ " line-height: 1.5;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " h2 {\n"
|
||||
+ " margin-top: 0;\n"
|
||||
+ " margin-bottom: 0.5rem;\n"
|
||||
+ " font-size: 2rem;\n"
|
||||
+ " font-weight: 500;\n"
|
||||
+ " line-height: 2rem;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " .content {\n"
|
||||
+ " margin-right: auto;\n"
|
||||
+ " margin-left: auto;\n"
|
||||
+ " padding-right: 15px;\n"
|
||||
+ " padding-left: 15px;\n"
|
||||
+ " width: 100%;\n"
|
||||
+ " box-sizing: border-box;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " @media (min-width: 800px) {\n"
|
||||
+ " .content {\n"
|
||||
+ " max-width: 760px;\n"
|
||||
+ " }\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " /* Components */\n"
|
||||
+ " a,\n"
|
||||
+ " a:visited {\n"
|
||||
+ " text-decoration: none;\n"
|
||||
+ " color: #06f;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " a:hover {\n"
|
||||
+ " text-decoration: underline;\n"
|
||||
+ " color: #003c97;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " input[type=\"text\"],\n"
|
||||
+ " input[type=\"password\"] {\n"
|
||||
+ " height: auto;\n"
|
||||
+ " width: 100%;\n"
|
||||
+ " font-size: 1rem;\n"
|
||||
+ " padding: 0.5rem;\n"
|
||||
+ " box-sizing: border-box;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " button {\n"
|
||||
+ " padding: 0.5rem 1rem;\n"
|
||||
+ " font-size: 1.25rem;\n"
|
||||
+ " line-height: 1.5;\n"
|
||||
+ " border: none;\n"
|
||||
+ " border-radius: 0.1rem;\n"
|
||||
+ " width: 100%;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " button.primary {\n"
|
||||
+ " color: #fff;\n"
|
||||
+ " background-color: #06f;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " .alert {\n"
|
||||
+ " padding: 0.75rem 1rem;\n"
|
||||
+ " margin-bottom: 1rem;\n"
|
||||
+ " line-height: 1.5;\n"
|
||||
+ " border-radius: 0.1rem;\n"
|
||||
+ " width: 100%;\n"
|
||||
+ " box-sizing: border-box;\n"
|
||||
+ " border-width: 1px;\n"
|
||||
+ " border-style: solid;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " .alert.alert-danger {\n"
|
||||
+ " color: #6b1922;\n"
|
||||
+ " background-color: #f7d5d7;\n"
|
||||
+ " border-color: #eab6bb;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " .alert.alert-success {\n"
|
||||
+ " color: #145222;\n"
|
||||
+ " background-color: #d1f0d9;\n"
|
||||
+ " border-color: #c2ebcb;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " .screenreader {\n"
|
||||
+ " position: absolute;\n"
|
||||
+ " clip: rect(0 0 0 0);\n"
|
||||
+ " height: 1px;\n"
|
||||
+ " width: 1px;\n"
|
||||
+ " padding: 0;\n"
|
||||
+ " border: 0;\n"
|
||||
+ " overflow: hidden;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " table {\n"
|
||||
+ " width: 100%;\n"
|
||||
+ " max-width: 100%;\n"
|
||||
+ " margin-bottom: 2rem;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " .table-striped tr:nth-of-type(2n + 1) {\n"
|
||||
+ " background-color: #e1e1e1;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " td {\n"
|
||||
+ " padding: 0.75rem;\n"
|
||||
+ " vertical-align: top;\n"
|
||||
+ " }\n"
|
||||
+ " \n"
|
||||
+ " /* Login / logout layouts */\n"
|
||||
+ " .login-form,\n"
|
||||
+ " .logout-form {\n"
|
||||
+ " max-width: 340px;\n"
|
||||
+ " padding: 0 15px 15px 15px;\n"
|
||||
+ " margin: 0 auto 2rem auto;\n"
|
||||
+ " box-sizing: border-box;\n"
|
||||
+ " }\n"
|
||||
+ " </style>\n"
|
||||
+ " </head>\n";
|
||||
//@formatter:on
|
||||
public static final String EXPECTED_HTML_HEAD = """
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<title>Please sign in</title>
|
||||
<style>
|
||||
/* General layout */
|
||||
body {
|
||||
font-family: system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
background-color: #eee;
|
||||
padding: 40px 0;
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
\s\s\s\s
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 2rem;
|
||||
font-weight: 500;
|
||||
line-height: 2rem;
|
||||
}
|
||||
\s\s\s\s
|
||||
.content {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
\s\s\s\s
|
||||
@media (min-width: 800px) {
|
||||
.content {
|
||||
max-width: 760px;
|
||||
}
|
||||
}
|
||||
\s\s\s\s
|
||||
/* Components */
|
||||
a,
|
||||
a:visited {
|
||||
text-decoration: none;
|
||||
color: #06f;
|
||||
}
|
||||
\s\s\s\s
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
color: #003c97;
|
||||
}
|
||||
\s\s\s\s
|
||||
input[type="text"],
|
||||
input[type="password"] {
|
||||
height: auto;
|
||||
width: 100%;
|
||||
font-size: 1rem;
|
||||
padding: 0.5rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
\s\s\s\s
|
||||
button {
|
||||
padding: 0.5rem 1rem;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.5;
|
||||
border: none;
|
||||
border-radius: 0.1rem;
|
||||
width: 100%;
|
||||
}
|
||||
\s\s\s\s
|
||||
button.primary {
|
||||
color: #fff;
|
||||
background-color: #06f;
|
||||
}
|
||||
\s\s\s\s
|
||||
.alert {
|
||||
padding: 0.75rem 1rem;
|
||||
margin-bottom: 1rem;
|
||||
line-height: 1.5;
|
||||
border-radius: 0.1rem;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
}
|
||||
\s\s\s\s
|
||||
.alert.alert-danger {
|
||||
color: #6b1922;
|
||||
background-color: #f7d5d7;
|
||||
border-color: #eab6bb;
|
||||
}
|
||||
\s\s\s\s
|
||||
.alert.alert-success {
|
||||
color: #145222;
|
||||
background-color: #d1f0d9;
|
||||
border-color: #c2ebcb;
|
||||
}
|
||||
\s\s\s\s
|
||||
.screenreader {
|
||||
position: absolute;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
\s\s\s\s
|
||||
table {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
\s\s\s\s
|
||||
.table-striped tr:nth-of-type(2n + 1) {
|
||||
background-color: #e1e1e1;
|
||||
}
|
||||
\s\s\s\s
|
||||
td {
|
||||
padding: 0.75rem;
|
||||
vertical-align: top;
|
||||
}
|
||||
\s\s\s\s
|
||||
/* Login / logout layouts */
|
||||
.login-form,
|
||||
.logout-form {
|
||||
max-width: 340px;
|
||||
padding: 0 15px 15px 15px;
|
||||
margin: 0 auto 2rem auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
""";
|
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this);
|
||||
|
||||
@@ -188,27 +190,30 @@ public class FormLoginBeanDefinitionParserTests {
|
||||
@Test
|
||||
public void getLoginWhenAutoConfigThenShowsDefaultLoginPage() throws Exception {
|
||||
this.spring.configLocations(this.xml("Simple")).autowire();
|
||||
// @formatter:off
|
||||
String expectedContent = "<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ EXPECTED_HTML_HEAD
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"content\">\n"
|
||||
+ " <form class=\"login-form\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2>Please sign in</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"screenreader\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"screenreader\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ " <button type=\"submit\" class=\"primary\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>";
|
||||
// @formatter:on
|
||||
String expectedContent = EXPECTED_HTML_HEAD + """
|
||||
<body>
|
||||
<div class="content">
|
||||
<form class="login-form" method="post" action="/login">
|
||||
<h2>Please sign in</h2>
|
||||
\s
|
||||
<p>
|
||||
<label for="username" class="screenreader">Username</label>
|
||||
<input type="text" id="username" name="username" placeholder="Username" required autofocus>
|
||||
</p>
|
||||
<p>
|
||||
<label for="password" class="screenreader">Password</label>
|
||||
<input type="password" id="password" name="password" placeholder="Password" required>
|
||||
</p>
|
||||
|
||||
|
||||
<button type="submit" class="primary">Sign in</button>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>""";
|
||||
this.mvc.perform(get("/login")).andExpect(content().string(expectedContent));
|
||||
}
|
||||
|
||||
@@ -221,31 +226,32 @@ public class FormLoginBeanDefinitionParserTests {
|
||||
@Test
|
||||
public void getLoginWhenConfiguredWithCustomAttributesThenLoginPageReflects() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithCustomAttributes")).autowire();
|
||||
// @formatter:off
|
||||
String expectedContent = "<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ EXPECTED_HTML_HEAD
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"content\">\n"
|
||||
+ " <form class=\"login-form\" method=\"post\" action=\"/signin\">\n"
|
||||
+ " <h2>Please sign in</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"screenreader\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"custom_user\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"screenreader\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"custom_pass\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ " <button type=\"submit\" class=\"primary\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>";
|
||||
this.mvc.perform(get("/login"))
|
||||
.andExpect(content().string(expectedContent));
|
||||
this.mvc.perform(get("/logout"))
|
||||
.andExpect(status().is3xxRedirection());
|
||||
// @formatter:on
|
||||
String expectedContent = EXPECTED_HTML_HEAD + """
|
||||
<body>
|
||||
<div class="content">
|
||||
<form class="login-form" method="post" action="/signin">
|
||||
<h2>Please sign in</h2>
|
||||
\s
|
||||
<p>
|
||||
<label for="username" class="screenreader">Username</label>
|
||||
<input type="text" id="username" name="custom_user" placeholder="Username" required autofocus>
|
||||
</p>
|
||||
<p>
|
||||
<label for="password" class="screenreader">Password</label>
|
||||
<input type="password" id="password" name="custom_pass" placeholder="Password" required>
|
||||
</p>
|
||||
|
||||
|
||||
<button type="submit" class="primary">Sign in</button>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>""";
|
||||
this.mvc.perform(get("/login")).andExpect(content().string(expectedContent));
|
||||
this.mvc.perform(get("/logout")).andExpect(status().is3xxRedirection());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user