I have a Spring Boot Web MVC application where I'm using a Bootstrap 4 template and Thymeleaf as view.
I'm facing a problem where a drop-down navigation item is rendering without styles and scripts when the containing page is mapped in the controller under more than one path segment. If the path consists only of one segment the component works as intended.
Page containing the component "menu.html"
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Menu</title>
<!-- Custom fonts for this template -->
<link href="/vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template -->
<link href="/css/sb-admin-2.min.css" rel="stylesheet">
<!-- Custom styles for this page -->
<link href="/vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<ul class="navbar-nav ml-auto">
<!-- Drop-Down Component -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small" th:text="${user.getName()}"></span>
<img class="img-profile rounded-circle" src="img/undraw_profile.svg" width="50" height="50">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="logoutModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="logoutModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="/login?logout=true">Logout</a>
</div>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
<!-- Page level plugins -->
<script src="vendor/datatables/jquery.dataTables.min.js"></script>
<script src="vendor/datatables/dataTables.bootstrap4.min.js"></script>
<!-- Page level custom scripts -->
<script src="js/demo/datatables-demo.js"></script>
</body>
</html>
Using the following mapping in my controller the component works fine:
#GetMapping(value = "/first-segment")
public String showModal(Model model) {
model.addAttribute("user", userService.getAuthenticatedUser());
return "menu";
}
But if I add a second segment no styling is displayed and the component can't be clicked on:
#GetMapping(value = "/first-segment/second-segment")
public String showModal(Model model) {
model.addAttribute("user", userService.getAuthenticatedUser());
return "menu";
}
Note
I'd also like to add that not all Bootstrap components don't render correctly under two path segments. As far as I've noticed only drop-down and modal components share this issue.
Replace:
<script src="vendor/jquery/jquery.min.js"></script>
with:
<script src="/vendor/jquery/jquery.min.js"></script>
Note the extra slash at the start. Otherwise, the Javascript file is supposed to be relative to the current file. That is why it worked for the first segment, but not the second segment.
By starting with a slash, it is always relative to the root of the path.
Below is the code that I wrote for verifying that the username and password fields present in the login page and the default text (Username in username box and Password in password box). I have also pasted the error that I am getting while executing this test. I did look around, did find a few things but nothing fits exactly in my case.
Update
Added the - HTML for the page as requested. I have pasted the whole but had to remove some of the HTML content due to the content limit for this.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>MS - Login
</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<link href="/assets/libs/jquery-icheck/skins/all.css" rel="stylesheet" data-pagespeed-lsc-url="testselenium.com/assets/libs/jquery-icheck/skins/all.css"/>
<link href="/assets/libs/bootstrap-tour/bootstrap-tour.min.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/libs/bootstrap-tour/bootstrap-tour.min.css"/>
<link href="/assets/libs/rickshaw/rickshaw.min.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/libs/rickshaw/rickshaw.min.css"/>
<link href="/assets/libs/morrischart/morris.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/libs/morrischart/morris.css"/>
<link href="/assets/libs/jquery-jvectormap/css/jquery-jvectormap-1.2.2.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/libs/jquery-jvectormap/css/jquery-jvectormap-1.2.2.css"/>
<link href="/assets/libs/jquery-clock/clock.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/libs/jquery-clock/clock.css"/>
<link href="/assets/libs/bootstrap-calendar/css/bic_calendar.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/libs/bootstrap-calendar/css/bic_calendar.css"/>
<link href="/assets/libs/sortable/sortable-theme-bootstrap.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/libs/sortable/sortable-theme-bootstrap.css"/>
<link href="/assets/libs/bootstrap-xeditable/css/bootstrap-editable.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/libs/bootstrap-xeditable/css/bootstrap-editable.css"/>
<link href="/assets/libs/jquery-notifyjs/styles/metro/notify-metro.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/libs/jquery-notifyjs/styles/metro/notify-metro.css"/>
<link href="/assets/css/sweetalert.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/css/sweetalert.css"/>
<link href="/assets/css/trumbowyg/trumbowyg.min.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/css/trumbowyg/trumbowyg.min.css"/>
<link href="/assets/libs/bootstrap-validator/css/bootstrapValidator.min.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/libs/bootstrap-validator/css/bootstrapValidator.min.css"/>
<link href="/assets/css/bootstrap-tagsinput.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/css/bootstrap-tagsinput.css"/>
<link href="/assets/libs/bootstrap-select/bootstrap-select.min.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/libs/bootstrap-select/bootstrap-select.min.css"/>
<link href="/assets/libs/weatherapp/weather.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/libs/weatherapp/weather.css"/>
<link href="/assets/css/flag-icon-css/flag-icon.min.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/css/flag-icon-css/flag-icon.min.css"/>
<link href="/assets/css/style.css" rel="stylesheet" type="text/css" data-pagespeed-lsc-url="testselenium.com/assets/css/style.css"/>
<link href="/assets/css/override.css" rel="stylesheet" data-pagespeed-lsc-url="testselenium.com/assets/css/override.css"/>
<link href="/assets/css/testme.css" rel="stylesheet" data-pagespeed-lsc-url="testselenium.com/assets/css/testme.css"/>
<link rel="apple-touch-icon" sizes="180x180" href="/assets/img/apple-touch-icon.png" data-pagespeed-lsc-url="testselenium.com/assets/img/apple-touch-icon.png">
<link rel="icon" type="image/png" href="/assets/img/favicon-32x32.png" sizes="32x32" data-pagespeed-lsc-url="testselenium.com/assets/img/favicon-32x32.png">
<link rel="icon" type="image/png" href="/assets/img/favicon-16x16.png" sizes="16x16" data-pagespeed-lsc-url="testselenium.com/assets/img/favicon-16x16.png">
<link rel="manifest" href="/assets/img/manifest.json">
<link rel="mask-icon" href="/assets/img/safari-pinned-tab.svg" color="#e74c3c">
<meta name="apple-mobile-web-app-title" content="testme">
<meta name="application-name" content="testme">
<meta name="msapplication-config" content="/assets/img/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<link rel="shortcut icon" href="/assets/img/favicon.ico" data-pagespeed-lsc-url="testselenium.com/assets/img/favicon.ico">
<link href="/assets/css/style-responsive.css" rel="stylesheet" data-pagespeed-lsc-url="testselenium.com/assets/css/style-responsive.css"/>
<script src="/assets/libs/jquery/jquery-1.11.1.min.js"></script>
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<script src="/assets/js/sweetalert.min.js"></script>
<script type="text/javascript">var timeoutDialog,mySwitch=[];</script>
<script data-pagespeed-no-defer>//<![CDATA[
(function(){function f(a,b,d){if(a.addEventListener)a.addEventListener(b,d,!1);else if(a.attachEvent)a.attachEvent("on"+b,d);else{var c=a["on"+b];a["on"+b]=function(){d.call(this);c&&c.call(this)}}};window.pagespeed=window.pagespeed||{};var g=window.pagespeed;function k(a){this.g=[];this.f=0;this.h=!1;this.j=a;this.i=null;this.l=0;this.b=!1;this.a=0}function l(a,b){var d=b.getAttribute("data-pagespeed-lazy-position");if(d)return parseInt(d,0);var d=b.offsetTop,c=b.offsetParent;c&&(d+=l(a,c));d=Math.max(d,0);b.setAttribute("data-pagespeed-lazy-position",d);return d}
function m(a,b){var d,c,e;if(!a.b&&(0==b.offsetHeight||0==b.offsetWidth))return!1;a:if(b.currentStyle)c=b.currentStyle.position;else{if(document.defaultView&&document.defaultView.getComputedStyle&&(c=document.defaultView.getComputedStyle(b,null))){c=c.getPropertyValue("position");break a}c=b.style&&b.style.position?b.style.position:""}if("relative"==c)return!0;e=0;"number"==typeof window.pageYOffset?e=window.pageYOffset:document.body&&document.body.scrollTop?e=document.body.scrollTop:document.documentElement&&
document.documentElement.scrollTop&&(e=document.documentElement.scrollTop);d=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;c=e;e=e+d;var h=b.getBoundingClientRect();h?(e=h.top-d,c=h.bottom):(h=l(a,b),d=h+b.offsetHeight,e=h-e,c=d-c);return e<=a.f&&0<=c+a.f}
k.prototype.m=function(a){p(a);var b=this;window.setTimeout(function(){var d=a.getAttribute("data-pagespeed-lazy-src");if(d)if((b.h||m(b,a))&&-1!=a.src.indexOf(b.j)){var c=a.parentNode,e=a.nextSibling;c&&c.removeChild(a);a.c&&(a.getAttribute=a.c);a.removeAttribute("onload");a.tagName&&"IMG"==a.tagName&&g.CriticalImages&&f(a,"load",function(){g.CriticalImages.checkImageForCriticality(this);b.b&&(b.a--,0==b.a&&g.CriticalImages.checkCriticalImages())});a.removeAttribute("data-pagespeed-lazy-src");a.removeAttribute("data-pagespeed-lazy-replaced-functions");
c&&c.insertBefore(a,e);if(c=a.getAttribute("data-pagespeed-lazy-srcset"))a.srcset=c,a.removeAttribute("data-pagespeed-lazy-srcset");a.src=d}else b.g.push(a)},0)};k.prototype.loadIfVisibleAndMaybeBeacon=k.prototype.m;k.prototype.s=function(){this.h=!0;q(this)};k.prototype.loadAllImages=k.prototype.s;function q(a){var b=a.g,d=b.length;a.g=[];for(var c=0;c<d;++c)a.m(b[c])}function t(a,b){return a.a?null!=a.a(b):null!=a.getAttribute(b)}
k.prototype.u=function(){for(var a=document.getElementsByTagName("img"),b=0,d;d=a[b];b++)t(d,"data-pagespeed-lazy-src")&&p(d)};k.prototype.overrideAttributeFunctions=k.prototype.u;function p(a){t(a,"data-pagespeed-lazy-replaced-functions")||(a.c=a.getAttribute,a.getAttribute=function(a){"src"==a.toLowerCase()&&t(this,"data-pagespeed-lazy-src")&&(a="data-pagespeed-lazy-src");return this.c(a)},a.setAttribute("data-pagespeed-lazy-replaced-functions","1"))}
g.o=function(a,b){function d(){if(!(c.b&&a||c.i)){var b=200;200<(new Date).getTime()-c.l&&(b=0);c.i=window.setTimeout(function(){c.l=(new Date).getTime();q(c);c.i=null},b)}}var c=new k(b);g.lazyLoadImages=c;f(window,"load",function(){c.b=!0;c.h=a;c.f=200;if(g.CriticalImages){for(var b=0,d=document.getElementsByTagName("img"),r=0,n;n=d[r];r++)-1!=n.src.indexOf(c.j)&&t(n,"data-pagespeed-lazy-src")&&b++;c.a=b;0==c.a&&g.CriticalImages.checkCriticalImages()}q(c)});0!=b.indexOf("data")&&((new Image).src=
b);f(window,"scroll",d);f(window,"resize",d)};g.lazyLoadInit=g.o;})();
pagespeed.lazyLoadInit(true, "/pagespeed_static/1.JiBnMqyl6S.gif");
//]]></script></head>
<body class="fixed-left login-page"><noscript><meta HTTP-EQUIV="refresh" content="0;url='testselenium.com/login?PageSpeed=noscript'" /><style><!--table,div,span,font,p{display:none} --></style><div style="display:block">Please click here if you are not redirected within a few seconds.</div></noscript>
<noscript>
<div class="nojs">
<p class="alert alert-danger"><strong><i class="fa fa-exclamation-triangle"></i> Warning:</strong> Features of testme rely on javascript. Please enable javascript from your browser preferences.</p>
</div>
</noscript>
<script type="text/javascript">var cookieEnabled=(navigator.cookieEnabled)?true:false;if(typeof navigator.cookieEnabled=="undefined"&&!cookieEnabled){document.cookie="cfstestcookie";cookieEnabled=(document.cookie.indexOf("cfstestcookie")!=-1)?true:false;}if(!cookieEnabled){document.write('<div class="nocookie"><p class="alert alert-danger"><strong><i class="fa fa-exclamation-triangle"></i> Warning:</strong> Features of testme require cookie, we have detected that your browser <strong>does not accept</strong> cookie at this moment. You can enable cookie via your browser\'s privacy preference settings.</p></div>');}</script><div aria-hidden="true" aria-labelledby="myModal" role="dialog" tabindex="-1" class="modal fade" id="myModal">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="md-close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
</div>
</div>
</div>
<div class="container">
<div class="full-content-center">
<p class="text-center"><script data-pagespeed-no-defer>//<![CDATA[
(function(){var g=this;function h(b,d){var a=b.split("."),c=g;a[0]in c||!c.execScript||c.execScript("var "+a[0]);for(var e;a.length&&(e=a.shift());)a.length||void 0===d?c[e]?c=c[e]:c=c[e]={}:c[e]=d};function l(b){var d=b.length;if(0<d){for(var a=Array(d),c=0;c<d;c++)a[c]=b[c];return a}return[]};function m(b){var d=window;if(d.addEventListener)d.addEventListener("load",b,!1);else if(d.attachEvent)d.attachEvent("onload",b);else{var a=d.onload;d.onload=function(){b.call(this);a&&a.call(this)}}};var n;function p(b,d,a,c,e){this.h=b;this.j=d;this.l=a;this.f=e;this.g={height:window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight,width:window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth};this.i=c;this.b={};this.a=[];this.c={}}function q(b,d){var a,c,e=d.getAttribute("data-pagespeed-url-hash");if(a=e&&!(e in b.c))if(0>=d.offsetWidth&&0>=d.offsetHeight)a=!1;else{c=d.getBoundingClientRect();var f=document.body;a=c.top+("pageYOffset"in window?window.pageYOffset:(document.documentElement||f.parentNode||f).scrollTop);c=c.left+("pageXOffset"in window?window.pageXOffset:(document.documentElement||f.parentNode||f).scrollLeft);f=a.toString()+","+c;b.b.hasOwnProperty(f)?a=!1:(b.b[f]=!0,a=a<=b.g.height&&c<=b.g.width)}a&&(b.a.push(e),b.c[e]=!0)}p.prototype.checkImageForCriticality=function(b){b.getBoundingClientRect&&q(this,b)};h("pagespeed.CriticalImages.checkImageForCriticality",function(b){n.checkImageForCriticality(b)});h("pagespeed.CriticalImages.checkCriticalImages",function(){r(n)});function r(b){b.b={};for(var d=["IMG","INPUT"],a=[],c=0;c<d.length;++c)a=a.concat(l(document.getElementsByTagName(d[c])));if(0!=a.length&&a[0].getBoundingClientRect){for(c=0;d=a[c];++c)q(b,d);a="oh="+b.l;b.f&&(a+="&n="+b.f);if(d=0!=b.a.length)for(a+="&ci="+encodeURIComponent(b.a[0]),c=1;c<b.a.length;++c){var e=","+encodeURIComponent(b.a[c]);131072>=a.length+e.length&&(a+=e)}b.i&&(e="&rd="+encodeURIComponent(JSON.stringify(t())),131072>=a.length+e.length&&(a+=e),d=!0);u=a;if(d){c=b.h;b=b.j;var f;if(window.XMLHttpRequest)f=new XMLHttpRequest;else if(window.ActiveXObject)try{f=new ActiveXObject("Msxml2.XMLHTTP")}catch(k){try{f=new ActiveXObject("Microsoft.XMLHTTP")}catch(v){}}f&&(f.open("POST",c+(-1==c.indexOf("?")?"?":"&")+"url="+encodeURIComponent(b)),f.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),f.send(a))}}}function t(){var b={},d=document.getElementsByTagName("IMG");if(0==d.length)return{};var a=d[0];if(!("naturalWidth"in a&&"naturalHeight"in a))return{};for(var c=0;a=d[c];++c){var e=a.getAttribute("data-pagespeed-url-hash");e&&(!(e in b)&&0<a.width&&0<a.height&&0<a.naturalWidth&&0<a.naturalHeight||e in b&&a.width>=b[e].o&&a.height>=b[e].m)&&(b[e]={rw:a.width,rh:a.height,ow:a.naturalWidth,oh:a.naturalHeight})}return b}var u="";h("pagespeed.CriticalImages.getBeaconData",function(){return u});h("pagespeed.CriticalImages.Run",function(b,d,a,c,e,f){var k=new p(b,d,a,e,f);n=k;c&&m(function(){window.setTimeout(function(){r(k)},0)})});})();pagespeed.CriticalImages.Run('/mod_pagespeed_beacon','testselenium.com/login','MeUgfxj8kW',false,false,'ycSmdtv-QaE');
//]]></script><img class="login-logo" data-pagespeed-lazy-src="https://n2s-customer-images.s3.amazonaws.com/c4ca4238a0b923820dcc509a6f75849b_228_36.png?79" alt="Logo" data-pagespeed-url-hash="1796267855" src="/pagespeed_static/1.JiBnMqyl6S.gif" onload="pagespeed.lazyLoadImages.`enter code here`loadIfVisibleAndMaybeBeacon(this);" onerror="this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);"></p>
<div class="login-wrap animated flipInX">
<div class="login-block">
<img data-pagespeed-lazy-src="/images/users/default-user.png" class="img-circle not-logged-avatar" data-pagespeed-url-hash="1346876537" data-pagespeed-lsc-url="testselenium.com/images/users/default-user.png" src="/pagespeed_static/1.JiBnMqyl6S.gif" onload="pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);" onerror="this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);">
<form id="login-form" action="/login" method="post"> <div class="alert alert-danger" role="alert" containerTag="div" containerItemTag="p" id="login-form_es_" style="display:none"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> <span style="font-weight:bold">Login failed</span>
<ul><li>dummy</li></ul></div>
<div class="form-group login-input">
<i class="fa fa-envelope overlay"></i>
<input placeholder="Email" class="form-control text-input" name="LoginForm[username]" id="LoginForm_username" type="text"/>
</div>
<div class="form-group login-input">
<i class="fa fa-key overlay"></i>
<input placeholder="Password" class="form-control text-input" name="LoginForm[password]" id="LoginForm_password" type="password"/>
</div>
<button type="submit" class="btn btn-success btn-lg btn-block">Login</button>
<div class="text-center">Forgot password?</div>
</form> </div>
</div>
</div>
</div>
<div class="md-overlay"></div>
<script type="text/javascript" data-pagespeed-no-defer>pagespeed.lazyLoadImages.overrideAttributeFunctions();</script><script>var resizefunc=[];</script>
<script src="/assets/libs/jquery/jquery-1.11.1.min.js"></script>
<script src="/assets/libs/bootstrap/js/bootstrap.min.js"></script>
<script src="/assets/libs/jqueryui/jquery-ui-1.10.4.custom.min.js"></script>
<script src="/assets/libs/jquery-ui-touch/jquery.ui.touch-punch.min.js"></script>
<script src="/assets/libs/jquery-detectmobile/detect.js"></script>
<script src="/assets/libs/jquery-animate-numbers/jquery.animateNumbers.js"></script>
<script src="/assets/libs/ios7-switch/ios7.switch.js"></script>
<script src="/assets/libs/fastclick/fastclick.js"></script>
<script src="/assets/libs/jquery-blockui/jquery.blockUI.js"></script>
<script src="/assets/libs/bootstrap-bootbox/bootbox.min.js"></script>
<script src="/assets/libs/jquery-slimscroll/jquery.slimscroll.js"></script>
<script src="/assets/libs/jquery-sparkline/jquery-sparkline.js"></script>
<script src="/assets/libs/nifty-modal/js/classie.js"></script>
<script src="/assets/libs/nifty-modal/js/modalEffects.js"></script>
<script src="/assets/libs/sortable/sortable.min.js"></script>
<script src="/assets/libs/bootstrap-fileinput/bootstrap.file-input.js"></script>
<script src="/assets/libs/bootstrap-select/bootstrap-select.min.js"></script>
<script src="/assets/libs/bootstrap-select2/select2.min.js"></script>
<script src="/assets/libs/magnific-popup/jquery.magnific-popup.min.js"></script>
<script src="/assets/libs/bootstrap-datepicker/js/bootstrap-datepicker.js"></script>
<script src="/assets/libs/jquery-icheck/icheck.min.js"></script>
<script src="/assets/libs/prettify/prettify.js"></script>
<script src="/assets/js/init.js"></script>
<script src="/assets/libs/jquery-notifyjs/notify.min.js"></script>
<script src="/assets/libs/jquery-notifyjs/styles/metro/notify-metro.js"></script>
<script src="/assets/js/pages/notifications.js"></script>
<script src="/assets/js/dismissable_popup.js"></script>
<script src="/assets/js/trumbowyg.min.js"></script>
<script src="/assets/js/bootstrap-tagsinput.min.js"></script>
<script src="/assets/js/typeahead.min.js"></script>
<script src="/assets/js/bloodhound.min.js"></script>
<script src="/assets/js/jBeep.min.js"></script>
<script src="/assets/js/utility.js"></script>
<script src="/assets/js/dropdown_selection_ui.js"></script>
<script type="text/javascript">var timeoutDialog,playBeepCounter=0,explorerAjaxRequest=null;var potentialRecipients=new Bloodhound({datumTokenizer:Bloodhound.tokenizers.obj.whitespace('text'),queryTokenizer:Bloodhound.tokenizers.whitespace,remote:{url:'/recipients?s=%QUERY',wildcard:"%QUERY"}});potentialRecipients.initialize();var afterModalLoaded=function(e){};var showModal=function(url){if($('#myModal').is(':visible')){reloadModal(url);return;}$("#myModal").modal({remote:url});};var reloadModal=function(target){$("#myModal .modal-content").html("<div class=\"modal-header\">Loading...</div>");$.get(target,null,function(data){$("#myModal .modal-content").html(data);});};var createSelectionUi=function(e){new DropDownSelectionUi('#btnAddressBook',{'event':'click','container':'.address_book','dataContainerClass':'.address_book_contents','dataUrl':'/recipients?s=','loadingHtml':"<li>Loading...</li>",'afterDataLoaded':function(){jQuery(document).off('click','.message_to').on('click','.message_to',function(){var parent=$(this).parent();if($(this).is(":checked")){$("#to").tagsinput('add',{"value":$(this).attr("value"),"text":parent.text().trim(),"type":parent.attr("class")});}else{$("#to").tagsinput('remove',{"value":$(this).attr("value"),"text":parent.text().trim(),"type":parent.attr("class")});}});},'dataGenerator':function(obj,reference){if(obj==null)return;if(reference.lookupArray==null){reference.lookupArray=$("#to").val().split(",");}var typeString="",checked="";if(obj.type!="individual"){typeString=" ("+obj.type.substr(0,1).toUpperCase()+obj.type.substr(1)+")";}if($.inArray(obj.value,reference.lookupArray)!=-1){checked=" checked=\"checked\""}return'<li class="'+obj.type+'"><input class="message_to" type="checkbox" value="'+obj.value+'"'+checked+' /> '+obj.text+''+typeString+'</li>';},'stateChanger':function(id){var object=jQuery(id+">i");if(object.hasClass('fa-plus')){object.removeClass('fa-plus').addClass('fa-minus');return;}object.removeClass('fa-minus').addClass('fa-plus');}});};var playBeep=function(){if(playBeepCounter<=2){jBeep('/assets/media/notification.wav');playBeepCounter++;return;}}
var closeModal=function(){$("#myModal").modal('hide');};$('[data-toggle="popover"]').popover({container:'body'});var initTagsInput=function(containerId,potentialRecipients){var el=$(containerId);el.tagsinput({tagClass:function(item){switch(item.type){case'group':return'label label-default';case'individual':return'label label-primary label-important';case'customer':case'storage':case'drive':case'alldrive':return'label label-success';}},itemValue:'value',itemText:'text',typeaheadjs:{name:'recipients',displayKey:'text',source:potentialRecipients.ttAdapter(),templates:{suggestion:function(item){return'<p>'+item.text+' - <strong>'+item.type.charAt(0).toUpperCase()+item.type.substr(1)+'</strong></p>';}}}});el.on('itemRemoved',function(event){});return el;};var initSummerNote=function(containerClass){$(containerClass).trumbowyg({btns:['bold','italic','underline','strikethrough','|','unorderedList','orderedList','|','justifyLeft','justifyCenter','justifyRight','justifyFull']});};var doCompose=function(user,name,email,type){var url='/emails/compose';type=type||"individual";if(user!=null){url+="/"+user;}if(!isNaN(email)&&email!=null){url+="/"+email;}afterModalLoaded=function(e){initSummerNote('.summernote-small');var el=initTagsInput('#to',potentialRecipients);if(name&&type){el.tagsinput('add',{"value":user+":"+type.charAt(0),"text":name,"type":type});}createSelectionUi();};showModal(url);};var doReply=function(user,name,email){doCompose(user,name,email,"individual");};var doReplyCustomer=function(customer,name){doCompose(customer,name,0,"customer");};var doComposeForStorageUsers=function(storage,name){doCompose(storage,name,0,"storage");};var doComposeForDriveUsers=function(drive,name,type){type=type||"drive";doCompose(drive,name,0,type);};(function($){$(document).ready(function(){var dPopup=new DismissablePopup(0),isMyDrivesMenuOpen=false;dPopup.reset();$(document).on('click',".my-drives",function(event){event.preventDefault();if(!isMyDrivesMenuOpen){var siblingUl=$(this).siblings().first();siblingUl.find("li").remove();siblingUl.append("<li>Loading <img src=\"/images/arrow-loader.gif\" /></li>");$.get('/drive-list',null,function(data){siblingUl.html(data);}).error(function(){siblingUl.html("<li><a href='#'>No drives available</a></li>");});isMyDrivesMenuOpen=true;return false;}isMyDrivesMenuOpen=false;return false;});$(document).on('click','.dropdown-toggle',function(){var span=$(this).find('span').eq(0);if(span&&parseInt(span.html())>0){span.html('');}});$(document).on('hidden.bs.modal','#myModal',function(e){$(e.target).removeData("bs.modal");});$(document).on('show.bs.modal','#myModal',function(e){$(e.target).find(".modal-content").html("<div class=\"modal-header\">Loading...</div>");});$(document).on('click','.btnmodal',function(evt){showModal($(this).attr('href'));evt.preventDefault();return false;});$(document).on('click','.btn-email-compose',function(evt){afterModalLoaded=function(e){initSummerNote('.summernote-small');initTagsInput('#to',potentialRecipients);createSelectionUi();};showModal($(this).attr('href'));evt.preventDefault();return false;});$(document).on('submit','#emailComposeForm',function(evt){$("#btn-send").attr("disabled","disabled").html('<i class="icon-paper-plane-1 fa-spin"></i> Sending...');$.post('/emails/compose',$(this).serialize(),function(response){if(response.status==true){$('#emailComposeForm')[0].reset();$('#to').tagsinput('removeAll');closeModal();swal("Sent!",response.reason==''?"Message Sent!":response.reason,response.reason==''?'success':'warning');return;}swal("Sorry!","Failed to send message to recipient(s), please try again later!","error");}).fail(function(){swal("Sorry!","Failed to send message to recipient(s), please try again later!","error");}).always(function(){$("#btn-send").removeAttr("disabled").html('<i class="icon-paper-plane-1"></i> Send');});evt.preventDefault();return false;});$(document).on('shown.bs.tooltip',function(e){setTimeout(function(){$(e.target).tooltip('hide');},3000);});$(document).on('loaded.bs.modal','#myModal',function(e){afterModalLoaded(e);afterModalLoaded=function(){};});$(document).on('click',"[class^='drives driveexplore']",function(evt){var driveClass=$(this).attr("class").replace('subdrop','').trim().split("_"),that=this,iconElement=$(this).find("i:first"),oldClass=iconElement.attr("class"),oldContent=iconElement.html();iconElement.removeClass(oldClass).html('<img width="20px" src="/images/circle-loader.gif" />');blockUI(null,"Please wait..");if(explorerAjaxRequest!=null){explorerAjaxRequest.abort();}explorerAjaxRequest=$.ajax({type:'POST',url:'/drive-alive',data:{id:driveClass[1]},success:function(data){switch(data){case"ok":var href=$(that).attr("href");if(""==href){break;}window.document.location=href;return;case"dead_server":autohidenotify('warning',"top center",'Storage Server for this drive is currently offline.','');break;case"maintenance_mode":autohidenotify('warning',"top center",'Drive is in maintenance mode.','');$(that).remove();break;default:autohidenotify('warning',"top center",'Selected drive does not exist.','');$(that).remove();break;}unblockUI();},error:function(){unblockUI();autohidenotify('warning',"top center",'Storage Server for this drive is currently offline.','');},complete:function(){iconElement.html(oldContent).addClass(oldClass);}});evt.preventDefault();return false;});});$(window).ready(function(){});})(jQuery);</script>
<a id="back-to-top" href="#" class="btn btn-primary btn-lg back-to-top" role="button" title="Click to return on the top page"><i class="fa fa-chevron-up"></i></a>
</body>
</html>
Code:
public void VerifyUserNamePassFieldPresence() {
assertElementPresent("//input[#name='name-of-this-field' and #type='text']");
driver.findElement(By.xpath(".//*[#id='LoginForm_username']")).getText();
System.out.println(driver.findElement(By.xpath(".//*[#id='LoginForm_username']")));
System.out.println("------------------------------------------------------------------------------------");
Assert.assertTrue(driver.findElement(By.xpath(".//*[#id='LoginForm_password']")).getText().matches("Password"));
}
Error:
FAILED: VerifyUserNamePassFieldPresence
java.lang.AssertionError: expected [true] but found [false]
at org.testng.Assert.fail(Assert.java:93)
at org.testng.Assert.failNotEquals(Assert.java:512)
at org.testng.Assert.assertTrue(Assert.java:41)
at org.testng.Assert.assertTrue(Assert.java:51)
at pages.LoginPage.VerifyUserNamePassFieldPresence(LoginPage.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:108)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:661)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:869)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1193)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:126)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
at org.testng.TestRunner.privateRun(TestRunner.java:744)
at org.testng.TestRunner.run(TestRunner.java:602)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:380)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:375)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:340)
at org.testng.SuiteRunner.run(SuiteRunner.java:289)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1301)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1226)
at org.testng.TestNG.runSuites(TestNG.java:1144)
at org.testng.TestNG.run(TestNG.java:1115)
at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:230)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:76)
Instead of calling
Assert.assertTrue(driver.findElement(By.xpath(".//*[#id='LoginForm_password']")).getText().matches("Password"));
You should first store the text value of your xPath in a String variable followed by Assert.assertEquals. In your case your code block will look like
String getPasswordText =
driver.findElement(By.xpath(".//*[#id='LoginForm_password']")).getText();
Assert.assertEquals(getPasswordText,"Password");
By dividing your code you would easily debug it and see whether getPasswordText has the desired expected text value or not.
Hope that helps !
I've tried everything to select this facebook button, by css, by partial link, by xpath. Can someone show me the syntax? HTML Code is below, the element is highlighted in blue.
This is the html for facebook Iframe login
<html>
<head>
<style type="text/css">
<title>My Photo Tab</title>
<base href="/">
<script src="https://apis.google.com/_/scs/apps-static/_/js/k=oz.gapi.en.U-RewQuh4JY.O/m=signin_annotation/exm=client,plusone/rt=j/sv=1/d=1/ed=1/am=AQ/rs=AGLTcCNj6EO7Q-0o28iG5EwDca54BMQrpw/t=zcms/cb=gapi.loaded_2" async="">
<script src="https://apis.google.com/_/scs/apps-static/_/js/k=oz.gapi.en.U-RewQuh4JY.O/m=plusone/exm=client/rt=j/sv=1/d=1/ed=1/am=AQ/rs=AGLTcCNj6EO7Q-0o28iG5EwDca54BMQrpw/t=zcms/cb=gapi.loaded_1" async="">
<script type="text/javascript" async="" src="//assets.pinterest.com/js/pinit_main.js">
<script id="adblade-sdk" src="http://web.adblade.com/js/ads/async/show.js">
<script id="facebook-jssdk" src="//connect.facebook.net/en_US/sdk.js">
<script id="google-platform-js" src="http://apis.google.com/js/platform.js" gapi_processed="true">
<script id="twitter-wjs" src="http://platform.twitter.com/widgets.js">
<script async="" src="//www.google-analytics.com/analytics.js">
<script src="https://apis.google.com/_/scs/apps-static/_/js/k=oz.gapi.en.U-RewQuh4JY.O/m=client/rt=j/sv=1/d=1/ed=1/am=AQ/rs=AGLTcCNj6EO7Q-0o28iG5EwDca54BMQrpw/t=zcms/cb=gapi.loaded_0" async="">
<script>
<link rel="stylesheet" href="assets/css/bootstrap.min.css?gb=0.0.3">
<link rel="stylesheet" href="assets/css/jquery.simplecolorpicker.css?gb=0.0.3">
<link rel="stylesheet" href="assets/css/style.css?gb=0.0.3">
<link rel="stylesheet" href="assets/css/shared.css?gb=0.0.3">
<link rel="stylesheet" href="assets/css/home.index.css?gb=0.0.3">
<link rel="stylesheet" href="assets/css/home.modals.css?gb=0.0.3">
<link rel="stylesheet" href="assets/css/languageSize.css?gb=0.0.3">
<link rel="stylesheet" href="assets/css/chosen/chosen.min.css?gb=0.0.3">
<link rel="stylesheet" href="assets/css/lp2.css?gb=0.0.3">
<meta content="http://myphototab.com" property="og:url">
<meta content="Your social photos on your new tab page!" property="og:title">
<meta content="http://cdn.myphototab.com/content/images/social.jpg" property="og:image">
<meta content="My Photo Tab" property="og:site_name">
<meta content="Turn your browser's boring new tab page into your personalized photo gallery!" property="og:description">
<meta content="summary_large_image" name="twitter:card">
<meta content="MyPhotoTab" name="twitter:site">
<meta content="MyPhotoTab" name="twitter:creator">
<meta content="Your social photos on your new tab page!" name="twitter:title">
<meta content="Turn your browser's boring new tab page into your personalized photo gallery!" name="twitter:description">
<meta content="http://cdn.myphototab.com/content/images/social.jpg" name="twitter:image:src">
<link type="text/css" rel="stylesheet" href="http://staticd.cdn.adblade.com/css/zones/zone1101.css">
<style type="text/css">
<script type="text/javascript" async="" src="http://edge.quantserve.com/quant.js">
<script type="text/javascript" async="" src="http://b.scorecardresearch.com/beacon.js?c1=8&c2=6864322&c3=&c4=&c5=&c6=&c10=&c15=">
<link type="text/css" rel="stylesheet" href="http://staticd.cdn.adblade.com/css/zones/zone1101.css">
<style type="text/css">
<script type="text/javascript" async="" src="http://edge.quantserve.com/quant.js">
<script type="text/javascript" async="" src="http://b.scorecardresearch.com/beacon.js?c1=8&c2=6864322&c3=&c4=&c5=&c6=&c10=&c15=">
<style type="text/css">
<style type="text/css">
</head>
<body class="isFF isWindows loggedout page-loaded modal-open Large en" style="background-image: none; background-color: rgb(192, 192, 192); overflow-y: auto;" data-twttr-rendered="true">
<input id="IsFromExtension" type="hidden" value="true">
<div class="pageWrapper" ng-view="">
<section id="homeView">
<div class="container body-content" style="">
<div id="myModal" class="modal fade in" data-backdrop="static" data-keyboard="false" aria-hidden="false" aria-labelledby="myModalLabel" role="dialog" tabindex="-1" style="display: block; visibility: visible;">
<div onload="showModal()" ng-include="partialUrl.Base">
<div id="modalWelcome" class="modal-dialog" style="display: block;">
<div class="modal-content gray-border">
<button class="close" ng-click="welcomeClose({trackingData: ['2', 'index-welcome', 'welcome-popup-close', '']})" data-dismiss="modal" type="button">
<div class="modal-body" style="">
<div class="modal-body-inner">
<div class="language">
<div class="title center langDir" style="direction: ltr;">
<div class="subtitle2 center langDir" translate="" style="direction: ltr;">My Photo Tab allows you to see your social and other photos on your browser's new tab page - FREE!</div>
<div class="socialButtons">
<div class="socialButtonsInner">
<div class="fblogin">
<fblogin>
<div class="fbLoginInner">
<fb:login-button class=" fb_iframe_widget" onlogin="FacebookLoginState();" scope="public_profile,email,user_photos,user_friends,publish_actions" size="xlarge" login_text=" Login with Facebook " fb-xfbml-state="rendered" fb-iframe-plugin-query="app_id=860682337328409&container_width=147&locale=en_US&login_text=%0A%20%20%20%20%20%20%20%20Login%20with%20Facebook%0A%20%20%20%20&scope=public_profile%2Cemail%2Cuser_photos%2Cuser_friends%2Cpublish_actions&sdk=joey&size=xlarge">
<span style="vertical-align: bottom; width: 290px; height: 39px;">
<iframe class="" width="1000px" height="1000px" frameborder="0" name="f138e5757ce176" allowtransparency="true" scrolling="no" title="fb:login_button Facebook Social Plugin" style="border: medium none; visibility: visible; width: 290px; height: 39px;" src="http://www.facebook.com/v2.1/plugins/login_button.php?app_id=860682337328409&channel=http%3A%2F%2Fstatic.ak.facebook.com%2Fconnect%2Fxd_arbiter%2F6Dg4oLkBbYq.js%3Fversion%3D41%23cb%3Df135579120b2446%26domain%3Dmyphototab.com%26origin%3Dhttp%253A%252F%252Fmyphototab.com%252Ff21d55794e16b1c%26relation%3Dparent.parent&container_width=147&locale=en_US&login_text=%0A%20%20%20%20%20%20%20%20Login%20with%20Facebook%0A%20%20%20%20&scope=public_profile%2Cemail%2Cuser_photos%2Cuser_friends%2Cpublish_actions&sdk=joey&size=xlarge">
<!DOCTYPE html>
<html id="facebook" class="" lang="en">
<head>
<body class="plugin gecko win x1 Locale_en_US" dir="ltr">
<div class="_li">
<div class="pluginSkinLight pluginFontHelvetica">
<div id="u_0_0" class="pluginLoginButton pluginLoginButtonXlarge" style="width: 300px;">
<div>
<div id="u_0_1" class="_4z_b _4z_8 _4z_c" tabindex="0" role="button">
<table class="uiGrid _51mz" cellspacing="0" cellpadding="0">
<tbody>
<tr class="_51mx">
<td class="_51m-">
<td class="_51m- _51mw">
<span class="_4z_9">
<span class="_4z_f fwb">Login with Facebook</span>
First switch to the iframe using: (As Saifur told name seems to be dynamic hence identifying element based on title)
driver.switchTo().frame(driver.findElement(By.xpath("//iframe[contains(#title,'Facebook Social Plugin')]")));
then click on the span as
new WebDriverWait(driver, 10).until(ExpectedConditions.presenceOfElementLocated(By.xpath("//span[contains(.,'Login with Facebook')]"))).click();
That's no button, that's a span.
Try: //span[text()='Login with Facebook']
Try xpath text based search
//span[contains(text(),'Login with Facebook')]
However, depending on the element load time you may need to add some explicit wait as well.
By xpath = By.xpath("//span[contains(text(),'Login with Facebook')]");
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(xpath));
myDynamicElement.click();
Edit
Just saw that page contains iframe. So, you need to use switchTo() to set focus into iframe before start looking for the element. See the API doc
//Looks like the name of ifame is also dynamic
//driver.switchTo().frame("fbf1ab674");
//assuming that's the only iframe on
driver.switchTo().frame(driver.findElement(By.cssSelector('iframe')));
driver.findElement(By.xpath("//span[contains(text(),'Login with Facebook')]")).click();
//switch back to default content when done working inside iframe
driver.switchTo().defaultContent();
I suspect for the same reason linkText and cssSelector you have used did not work.
Also, please try to post html instead of image for future reference which is much easier to read and find possible issues.
With Firefox (firebug) and Chrome (chromebug), u can copy the xpath of each selected item. Very useful when developing with Selenium!
Check out this wikihow page and u will like it!
http://m.wikihow.com/Find-XPath-Using-Firebug
Meanwhile it should also be available in Firefox inspector.