diff --git a/CHANGES.md b/CHANGES.md index bbad1ac8374..49529a0678a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,7 @@ Changes ### v4.4-r1 * 2024-07-15 - Development: Rename master branch to main, please update your clones. +* 2024-05-14 - Improvement: Limit the max-width of the navbar logo if it is too broad or has a special aspect ratio #544 * 2024-07-13 - Upgrade: Make the \theme_boost_union\task\purge_cache task non-blocking as this has been deprecated in Moodle core. * 2024-07-13 - Bugfix: Adopt fix for MDL-82397 before its integration into Moodle core, relates to #691. * 2024-07-12 - Upgrade: Adapt the course index icon feature visually to the new icon sizes. diff --git a/README.md b/README.md index bad258e1b27..2343299a117 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,10 @@ Here, you can upload a full logo to be used as decoration. This image is especia Here, you can upload a compact version of the same logo as above, such as an emblem, shield or icon. This image is especially used in the navigation bar at the top of each Moodle page. The image should be clear even at small sizes. +###### Logo Maxwidth + +If the logo for the navbar on the top left is too wide or has a special aspect ratio, you can limit the logo's maximum width. Use css definition to limit the max-width. + ##### Favicon ###### Favicon diff --git a/amd/build/smartmenu.min.js b/amd/build/smartmenu.min.js index f7a25da1bd8..4dd3ae874ed 100644 --- a/amd/build/smartmenu.min.js +++ b/amd/build/smartmenu.min.js @@ -1,10 +1 @@ -/** - * Theme Boost Union - JS for smart menu to realize the third level submenu support. - * - * @module theme_boost_union/smartmenu - * @copyright 2023 bdecent GmbH - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -define("theme_boost_union/smartmenu",["jquery","core/moremenu"],(function($){const Selectors_dropDownMenu="dropdownmoremenu",Selectors_forceOut="force-menu-out",Selectors_navLink="nav-link",Selectors_dropDownItem="dropdown-item",Selectors_classes={dropDownMenuList:".dropdownmoremenu ul.dropdown-menu",forceOut:".dropdownmoremenu .force-menu-out"},hideSubmenus=target=>{var visibleMenu=document.querySelectorAll("nav.moremenu .dropdown-submenu.show");null!==visibleMenu&&visibleMenu.forEach((el=>{el!=target&&el.classList.remove("show")}))},setOutMenuPositions=navMenu=>{if(null!=navMenu){var li=Array.from(navMenu.children).filter((e=>!e.classList.contains(Selectors_dropDownMenu))),position=0;li.forEach((menu=>{position=li.indexOf(menu),menu.dataset.orgposition=position}));var moreMenu=navMenu.querySelector(Selectors_classes.dropDownMenuList);Array.from(moreMenu.children).forEach((menu=>{menu.dataset.orgposition=position++}))}},moveOutMoreMenu=navMenu=>{if(null!==navMenu){var li=Array.from(navMenu.children).reverse().filter((e=>!e.classList.contains(Selectors_forceOut)&&!e.classList.contains(Selectors_dropDownMenu)));if(!(li.length<1)){var outMenus=navMenu.querySelectorAll(Selectors_classes.forceOut),menuslist=[];if(null!==outMenus){outMenus.forEach((menu=>{menu.querySelector("a").classList.remove(Selectors_dropDownItem),menu.querySelector("a").classList.add(Selectors_navLink),menuslist.push(menu),menu.parentNode.removeChild(menu)}));var moveMenus=[];menuslist.forEach((menu=>{navMenu.insertBefore(menu,navMenu.lastElementChild)&&li.length>0&&moveMenus.push(li.shift())})),moveMenus.forEach((menu=>{navMenu.insertBefore(menu,navMenu.lastElementChild)})),window.dispatchEvent(new Event("resize")),(navMenu=>{Array.from(navMenu.children).sort(((a,b)=>a.dataset.orgposition-b.dataset.orgposition)).forEach((menu=>navMenu.appendChild(menu)))})(navMenu)}}}};return{init:()=>{(()=>{var submenu=document.querySelectorAll("nav.moremenu .dropdown-submenu");null!==submenu&&submenu.forEach((item=>{item.addEventListener("click",(e=>{var target=e.currentTarget;hideSubmenus(target),target.classList.toggle("show"),e.stopPropagation()}))})),$(document).on("hidden.bs.dropdown",(e=>{var submenus=e.relatedTarget.parentNode.querySelectorAll(".dropdown-submenu.show");null!==submenus&&submenus.forEach((e=>e.classList.remove("show")))})),document.addEventListener("click",(e=>{var dropdown=e.target.closest(".dropdownmoremenu"),subMenu=e.target.closest(".dropdown-submenu");dropdown&&null!==subMenu&&(dropdown.querySelectorAll(".dropdown-submenu.show").forEach((menu=>{menu.classList.remove("show")})),subMenu.classList.toggle("show"));var dropdownMenu=e.target.parentNode.classList.contains("dropdown");dropdown&&dropdownMenu&&dropdown.querySelectorAll(".dropdown-menu.show").forEach((menu=>{menu!=e.target.closest(".dropdown-menu")&&menu.classList.remove("show")}))}),!0);var helpIcon=document.querySelectorAll(".moremenu .dropdown .menu-helpicon");null!==helpIcon&&helpIcon.forEach((icon=>{icon.addEventListener("click",(e=>{e.stopPropagation()}))}))})(),(()=>{var cards=document.querySelectorAll(".card-dropdown.card-overflow-no-wrap");if(null!==cards){var scrollStart,scrollMoved;let startPos,scrollPos;cards.forEach((card=>{var scrollElement=card.querySelector(".dropdown-menu");scrollElement.addEventListener("mousedown",(e=>{scrollStart=!0;var target=e.currentTarget.querySelector(".card-block-wrapper");startPos=e.pageX,scrollPos=target.scrollLeft})),scrollElement.addEventListener("mousemove",(e=>{if(e.preventDefault(),!scrollStart)return;scrollMoved=!0;var target=e.currentTarget.querySelector(".card-block-wrapper");const scroll=e.pageX-startPos;target.scrollLeft=scrollPos-scroll})),scrollElement.addEventListener("click",(e=>{scrollMoved&&(e.preventDefault(),scrollMoved=!1),e.stopPropagation()})),scrollElement.addEventListener("mouseleave",(()=>{scrollStart=!1,scrollMoved=!1})),scrollElement.addEventListener("mouseup",(()=>{scrollStart=!1}))}))}})(),(()=>{var primaryNav=document.querySelector(".primary-navigation ul.more-nav");null!=primaryNav&&(setOutMenuPositions(primaryNav),moveOutMoreMenu(primaryNav));var menuBar=document.querySelector("nav.menubar ul.more-nav");null!=menuBar&&(setOutMenuPositions(menuBar),moveOutMoreMenu(menuBar)),window.onresize=e=>{e.isTrusted&&(moveOutMoreMenu(primaryNav),moveOutMoreMenu(menuBar))}})()}}})); - -//# sourceMappingURL=smartmenu.min.js.map \ No newline at end of file +define(["jquery","core/moremenu"],function($){const Selectors={dropDownMenu:"dropdownmoremenu",forceOut:"force-menu-out",navLink:"nav-link",dropDownItem:"dropdown-item",classes:{dropDownMenuList:".dropdownmoremenu ul.dropdown-menu",forceOut:".dropdownmoremenu .force-menu-out"}};const addSubmenu=()=>{var submenu=document.querySelectorAll("nav.moremenu .dropdown-submenu");if(submenu!==null){submenu.forEach(item=>{item.addEventListener("click",e=>{var target=e.currentTarget;hideSubmenus(target);target.classList.toggle("show");e.stopPropagation()})})}$(document).on("hidden.bs.dropdown",e=>{var target=e.relatedTarget.parentNode;var submenus=target.querySelectorAll(".dropdown-submenu.show");if(submenus!==null){submenus.forEach(e=>e.classList.remove("show"))}});document.addEventListener("click",e=>{var dropdown=e.target.closest(".dropdownmoremenu");var subMenu=e.target.closest(".dropdown-submenu");if(dropdown&&subMenu!==null){dropdown.querySelectorAll(".dropdown-submenu.show").forEach(menu=>{menu.classList.remove("show")});subMenu.classList.toggle("show")}var dropdownMenu=e.target.parentNode.classList.contains("dropdown");if(dropdown&&dropdownMenu){dropdown.querySelectorAll(".dropdown-menu.show").forEach(menu=>{if(menu!=e.target.closest(".dropdown-menu")){menu.classList.remove("show")}})}},true);var helpIcon=document.querySelectorAll(".moremenu .dropdown .menu-helpicon");if(helpIcon!==null){helpIcon.forEach(icon=>{icon.addEventListener("click",e=>{e.stopPropagation()})})}};const hideSubmenus=target=>{var visibleMenu=document.querySelectorAll("nav.moremenu .dropdown-submenu.show");if(visibleMenu!==null){visibleMenu.forEach(el=>{if(el!=target){el.classList.remove("show")}})}};const cardScroll=()=>{var cards=document.querySelectorAll(".card-dropdown.card-overflow-no-wrap");if(cards!==null){var scrollStart;var scrollMoved;let startPos,scrollPos;cards.forEach(card=>{var scrollElement=card.querySelector(".dropdown-menu");scrollElement.addEventListener("mousedown",e=>{scrollStart=true;var target=e.currentTarget.querySelector(".card-block-wrapper");startPos=e.pageX;scrollPos=target.scrollLeft});scrollElement.addEventListener("mousemove",e=>{e.preventDefault();if(!scrollStart){return}scrollMoved=true;var target=e.currentTarget.querySelector(".card-block-wrapper");const scroll=e.pageX-startPos;target.scrollLeft=scrollPos-scroll});scrollElement.addEventListener("click",e=>{if(scrollMoved){e.preventDefault();scrollMoved=false}e.stopPropagation()});scrollElement.addEventListener("mouseleave",()=>{scrollStart=false;scrollMoved=false});scrollElement.addEventListener("mouseup",()=>{scrollStart=false})})}};const autoCollapse=()=>{var primaryNav=document.querySelector(".primary-navigation ul.more-nav");if(primaryNav!=undefined){setOutMenuPositions(primaryNav);moveOutMoreMenu(primaryNav)}var menuBar=document.querySelector("nav.menubar ul.more-nav");if(menuBar!=undefined){setOutMenuPositions(menuBar);moveOutMoreMenu(menuBar)}window.onresize=e=>{if(e.isTrusted){moveOutMoreMenu(primaryNav);moveOutMoreMenu(menuBar)}}};const setOutMenuPositions=navMenu=>{if(navMenu===undefined||navMenu===null){return}var li=Array.from(navMenu.children).filter(e=>!e.classList.contains(Selectors.dropDownMenu));var position=0;li.forEach(menu=>{position=li.indexOf(menu);menu.dataset.orgposition=position});var moreMenu=navMenu.querySelector(Selectors.classes.dropDownMenuList);Array.from(moreMenu.children).forEach(menu=>{menu.dataset.orgposition=position++})};const reArrangeMenuOrgPositions=navMenu=>{var li=Array.from(navMenu.children).sort((a,b)=>a.dataset.orgposition-b.dataset.orgposition);li.forEach(menu=>navMenu.appendChild(menu))};const moveOutMoreMenu=navMenu=>{if(navMenu===null){return}var li=Array.from(navMenu.children).reverse().filter(e=>!e.classList.contains(Selectors.forceOut)&&!e.classList.contains(Selectors.dropDownMenu));if(li.length<1){return}var outMenus=navMenu.querySelectorAll(Selectors.classes.forceOut);var menuslist=[];if(outMenus===null){return}outMenus.forEach(menu=>{menu.querySelector("a").classList.remove(Selectors.dropDownItem);menu.querySelector("a").classList.add(Selectors.navLink);menuslist.push(menu);menu.parentNode.removeChild(menu)});var moveMenus=[];menuslist.forEach(menu=>{if(navMenu.insertBefore(menu,navMenu.lastElementChild)&&li.length>0){moveMenus.push(li.shift())}});moveMenus.forEach(menu=>{navMenu.insertBefore(menu,navMenu.lastElementChild)});window.dispatchEvent(new Event("resize"));reArrangeMenuOrgPositions(navMenu)};return{init:()=>{addSubmenu();cardScroll();autoCollapse()}}}); \ No newline at end of file diff --git a/lang/en/theme_boost_union.php b/lang/en/theme_boost_union.php index 1c2fa2eb024..5b8b7b28311 100644 --- a/lang/en/theme_boost_union.php +++ b/lang/en/theme_boost_union.php @@ -170,6 +170,9 @@ $string['bootstrapcolordangersetting_desc'] = 'The Bootstrap color for "Danger"'; // ... Section: Navbar. $string['navbarheading'] = 'Navbar'; +// ... Section: Navbar logo max width. +$string['maxlogowidth'] = 'Maximal width of logo'; +$string['maxlogowidth_desc'] = 'If the logo is too broad or has a special aspect ratio, you can set the maximal width of the logo in the navbar header. Use CSS notation. Possible values can have some digits and end with `px`, `%`, `vw` or the field can be left empty, if you do not want to use this setting.'; // ... ... Setting: Navbar color. $string['navbarcolorsetting'] = 'Navbar color'; $string['navbarcolorsetting_desc'] = 'With this setting, you can change the navbar color from the default light navbar to a dark one or a colored one.'; diff --git a/lib.php b/lib.php index 8b7404dfe3e..af1edba97a5 100644 --- a/lib.php +++ b/lib.php @@ -365,6 +365,9 @@ function theme_boost_union_get_extra_scss($theme) { // Setting: Activity icon purpose. $content .= theme_boost_union_get_scss_for_activity_icon_purpose($theme); + // Setting: Navbar and icon styles. + $content .= theme_boost_union_get_scss_navbar($theme); + // Setting: Mark external links. $content .= theme_boost_union_get_scss_to_mark_external_links($theme); diff --git a/locallib.php b/locallib.php index e6e9a366043..4fce2b073ba 100644 --- a/locallib.php +++ b/locallib.php @@ -1667,6 +1667,25 @@ function theme_boost_union_get_scss_courseoverview_block($theme) { return $scss; } +/** + * Returns the SCSS code to be used in the navbar. The first usage is a logo icon that is possibly too broad and needs + * reduced to fit the navbar. See theme_boost_union_maxlogowidth for further details + * + * @param theme_config $theme The theme config object. + * @return string + */ +function theme_boost_union_get_scss_navbar($theme) { + // Initialize SCSS snippet. + $scss = ''; + + // Set variables which are read in settings by the logo maxwidth values. + if (get_config('theme_boost_union', 'maxlogowidth')) { + $scss .= ".navbar-brand img.logo{max-width:".get_config('theme_boost_union', 'maxlogowidth').";height:auto;}\n"; + } + + return $scss; +} + /** * Helper function which returns an array of login methods on the login page. * diff --git a/settings.php b/settings.php index beb6d5214ad..3281914ff88 100644 --- a/settings.php +++ b/settings.php @@ -126,6 +126,10 @@ // (with 3 or 4 digits) or a viewport width number (from 0 to 100). $widthregex = '/^((\d{1,2}|100)%)|((\d{1,2}|100)vw)|(\d{3,4}px)$/'; + // Prepare regular expression for checking if the value is a percent number (from 0% to 100%) or a pixel number + // (with 2 or 3 digits) or a viewport width number (from 0 to 100). Additionally the field can be left blank. + $smallsizeoremptyregex = '/^((\d{1,2}|100)%)|((\d{1,2}|100)vw)|(\d{2,3}px)|(^(?!.*\S))$/'; + // Create Look settings page with tabs // (and allow users with the theme/boost_union:configure capability to access it). $page = new theme_boost_admin_settingspage_tabs('theme_boost_union_look', @@ -396,6 +400,15 @@ $setting->set_updatedcallback('theme_reset_all_caches'); $tab->add($setting); + // Setting: add extra SCSS if logo icon is too broad / wrong aspect ratio. + $name = 'theme_boost_union/maxlogowidth'; + $title = get_string('maxlogowidth', 'theme_boost_union', null, true); + $description = get_string('maxlogowidth_desc', 'theme_boost_union', null, true); + $default = ''; + $setting = new admin_setting_configtext($name, $title, $description, $default, $smallsizeoremptyregex, 6); + $setting->set_updatedcallback('theme_reset_all_caches'); + $tab->add($setting); + // Create favicon heading. $name = 'theme_boost_union/faviconheading'; $title = get_string('faviconheading', 'theme_boost_union', null, true); diff --git a/tests/behat/theme_boost_union_looksettings_sitebranding.feature b/tests/behat/theme_boost_union_looksettings_sitebranding.feature index 12a91169895..a861207b196 100644 --- a/tests/behat/theme_boost_union_looksettings_sitebranding.feature +++ b/tests/behat/theme_boost_union_looksettings_sitebranding.feature @@ -20,12 +20,10 @@ Feature: Configuring the theme_boost_union plugin for the "Site branding" tab on @javascript @_file_upload Scenario: Setting: Logo - Upload a custom logo to the theme When I log in as "admin" - And Behat debugging is disabled And I navigate to "Appearance > Boost Union > Look" in site administration And I click on "Site branding" "link" in the "#adminsettings .nav-tabs" "css_element" And I upload "theme/boost_union/tests/fixtures/moodlelogo.png" file to "Logo" filemanager And I press "Save changes" - And Behat debugging is enabled And I log out And I click on "Log in" "link" in the ".logininfo" "css_element" # We can't check the uploaded image file visually, but we can verify that the compact logo is shipped from the theme_boost_union global logo filearea. @@ -50,12 +48,10 @@ Feature: Configuring the theme_boost_union plugin for the "Site branding" tab on @javascript @_file_upload Scenario: Setting: Compact logo - Upload a PNG logo to the theme and check that it is resized When I log in as "admin" - And Behat debugging is disabled And I navigate to "Appearance > Boost Union > Look" in site administration And I click on "Site branding" "link" in the "#adminsettings .nav-tabs" "css_element" And I upload "theme/boost_union/tests/fixtures/moodlelogo.png" file to "Logo" filemanager And I press "Save changes" - And Behat debugging is enabled And I log out And I click on "Log in" "link" in the ".logininfo" "css_element" Then "//div[@id='loginlogo']//img[@id='logoimage'][contains(@src, 'pluginfile.php/1/theme_boost_union/logo/0x200/')]" "xpath_element" should exist @@ -63,12 +59,10 @@ Feature: Configuring the theme_boost_union plugin for the "Site branding" tab on @javascript @_file_upload Scenario: Setting: Compact logo - Upload a SVG logo to the theme and check that it is not resized When I log in as "admin" - And Behat debugging is disabled And I navigate to "Appearance > Boost Union > Look" in site administration And I click on "Site branding" "link" in the "#adminsettings .nav-tabs" "css_element" And I upload "theme/boost_union/tests/fixtures/moodlelogo.svg" file to "Logo" filemanager And I press "Save changes" - And Behat debugging is enabled And I log out And I click on "Log in" "link" in the ".logininfo" "css_element" Then "//div[@id='loginlogo']//img[@id='logoimage'][contains(@src, 'pluginfile.php/1/theme_boost_union/logo/1/')]" "xpath_element" should exist @@ -76,12 +70,10 @@ Feature: Configuring the theme_boost_union plugin for the "Site branding" tab on @javascript @_file_upload Scenario: Setting: Compact logo - Upload a custom compact logo to the theme When I log in as "admin" - And Behat debugging is disabled And I navigate to "Appearance > Boost Union > Look" in site administration And I click on "Site branding" "link" in the "#adminsettings .nav-tabs" "css_element" And I upload "theme/boost_union/tests/fixtures/moodlelogo.png" file to "Compact logo" filemanager And I press "Save changes" - And Behat debugging is enabled And I am on site homepage # We can't check the uploaded image file visually, but we can verify that the compact logo is shipped from the theme_boost_union global logo filearea. Then "//nav[contains(@class, 'navbar')]//img[contains(@class, 'logo')][contains(@src, 'pluginfile.php/1/theme_boost_union/logocompact')][contains(@src, 'moodlelogo.png')]" "xpath_element" should exist @@ -100,39 +92,72 @@ Feature: Configuring the theme_boost_union plugin for the "Site branding" tab on And I am on site homepage Then ".navbar .logo" "css_element" should not exist + @javascript + Scenario Outline: Setting: Logo max-width - limit logo width readout from theme_config entry + Given the following config values are set as admin: + | config | value | plugin | + | maxlogowidth | | theme_boost_union | + And the theme cache is purged and the theme is reloaded + When I log in as "student1" + And I am on site homepage + Then DOM element ".navbar-brand .logo" should have computed style "" "" + And DOM element ".navbar-brand .logo" should have computed style "height" "auto" + + Examples: + | css-name | css-rule | + | max-width | 100px | + | max-width | 10vw | + | max-width | 13% | + + @javascript + Scenario: Setting: Logo max-width - limit logo width readout from theme_config entry (countercheck) + When I log in as "admin" + And I navigate to "Appearance > Boost Union > Look" in site administration + And I click on "Site branding" "link" in the "#adminsettings .nav-tabs" "css_element" + And I set the field "Maximal width of logo" to "" + And I press "Save changes" + And I am on site homepage + And the theme cache is purged and the theme is reloaded + Then DOM element ".navbar-brand .logo" should have computed style "height" "100%" + + @javascript + Scenario: Setting: Logo max-width - limit logo through admin settings - check regex to limit entry (countercheck) + When I log in as "admin" + And I navigate to "Appearance > Boost Union > Look" in site administration + And I click on "Site branding" "link" in the "#adminsettings .nav-tabs" "css_element" + And I set the field "Maximal width of logo" to "2px" + And I press "Save changes" + Then I should not see "Changes saved" + And I should see "Some settings were not changed due to an error." + And I should see "This value is not valid" + @javascript @_file_upload Scenario: Setting: Compact logo - Upload a PNG compact logo to the theme and check that it is resized When I log in as "admin" - And Behat debugging is disabled And I navigate to "Appearance > Boost Union > Look" in site administration And I click on "Site branding" "link" in the "#adminsettings .nav-tabs" "css_element" And I upload "theme/boost_union/tests/fixtures/moodlelogo.png" file to "Compact logo" filemanager And I press "Save changes" - And Behat debugging is enabled And I am on site homepage Then "//nav[contains(@class, 'navbar')]//img[contains(@class, 'logo')][contains(@src, 'pluginfile.php/1/theme_boost_union/logocompact/300x300/')]" "xpath_element" should exist @javascript @_file_upload Scenario: Setting: Compact logo - Upload a SVG compact logo to the theme and check that it is not resized When I log in as "admin" - And Behat debugging is disabled And I navigate to "Appearance > Boost Union > Look" in site administration And I click on "Site branding" "link" in the "#adminsettings .nav-tabs" "css_element" And I upload "theme/boost_union/tests/fixtures/moodlelogo.svg" file to "Compact logo" filemanager And I press "Save changes" - And Behat debugging is enabled And I am on site homepage Then "//nav[contains(@class, 'navbar')]//img[contains(@class, 'logo')][contains(@src, 'pluginfile.php/1/theme_boost_union/logocompact/1/')]" "xpath_element" should exist @javascript @_file_upload Scenario: Setting: Favicon - Upload a custom favicon to the theme When I log in as "admin" - And Behat debugging is disabled And I navigate to "Appearance > Boost Union > Look" in site administration And I click on "Site branding" "link" in the "#adminsettings .nav-tabs" "css_element" And I upload "theme/boost_union/tests/fixtures/favicon.ico" file to "Favicon" filemanager And I press "Save changes" - And Behat debugging is enabled # We can't check the uploaded favicon visually, but we can verify that the site's favicon is not shipped by pluginfile.php (for uploaded files) and not by theme/image.php (for image files from disk) anymore. Then "//head//link[contains(@rel, 'shortcut')][contains(@href, 'pluginfile.php/1/theme_boost_union/favicon')][contains(@href, 'favicon.ico')]" "xpath_element" should exist And "//head//link[contains(@rel, 'shortcut')][contains(@href, 'theme/image.php/boost_union')][contains(@href, 'favicon')]" "xpath_element" should not exist @@ -158,12 +183,10 @@ Feature: Configuring the theme_boost_union plugin for the "Site branding" tab on | config | value | plugin | | backgroundimageposition | | theme_boost_union | When I log in as "admin" - And Behat debugging is disabled And I navigate to "Appearance > Boost Union > Look" in site administration And I click on "Site branding" "link" in the "#adminsettings .nav-tabs" "css_element" And I upload "theme/boost_union/tests/fixtures/login_bg1.jpg" file to "Background image" filemanager And I press "Save changes" - And Behat debugging is enabled And I am on site homepage Then DOM element "body" should have computed style "background-position" ""