diff --git a/CHANGELOG.md b/CHANGELOG.md index d57a79ccd..64380c641 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to AET will be documented in this file. ## Unreleased **List of changes that are finished but not yet released in any final version.** +- [PR-289](https://github.com/Cognifide/aet/pull/289) User now stays on the same tab while navigating between URLs - [PR-271](https://github.com/Cognifide/aet/pull/271) Added possibility to override name parameter from the aet client - [PR-268](https://github.com/Cognifide/aet/pull/268) Bobcat upgrade to version 1.4.0 - [PR-279](https://github.com/Cognifide/aet/pull/279) Upgrade for some of libraries used by AET diff --git a/report/src/main/webapp/app/components/keyboardShortcuts.directive.js b/report/src/main/webapp/app/components/keyboardShortcuts.directive.js index 0f0cbf85c..9da4dcf47 100644 --- a/report/src/main/webapp/app/components/keyboardShortcuts.directive.js +++ b/report/src/main/webapp/app/components/keyboardShortcuts.directive.js @@ -121,10 +121,11 @@ define(['angularAMD', 'userSettingsService'], function (angularAMD) { function traverseTreeDown(currentItem, testContainer, suiteContainer, testUrlSelector) { - var currentTest, - currentLocation = window.location.hash, - $nextElement, - $firstElementInTest; + var currentTest; + var currentLocation = window.location.hash; + var $nextElement; + var $firstElementInTest; + var currentTabLabel; if (!(ifRootPage(currentLocation, '/url/') || ifRootPage( currentLocation, '/test/') || ifRootPage(currentLocation, @@ -141,36 +142,36 @@ define(['angularAMD', 'userSettingsService'], function (angularAMD) { if (!_.isEmpty($(suiteContainer).nextAll( '.aside-report:not(.is-hidden)').first().find( '.test-name'))) { - testContainer.removeClass('is-active'); - currentItem.removeClass('is-active'); - toggleNextTest(suiteContainer); + currentTabLabel = getCurrentTabLabel(); $nextElement = suiteContainer.nextAll( - '.aside-report:not(.is-hidden)').first(); - $nextElement.addClass('is-expanded'); - $nextElement.children().first().addClass('is-active'); - scrollTo($nextElement.find('.is-active')); + '.aside-report:not(.is-hidden)').first(); + handleStyling(testContainer, currentItem, $nextElement); + toggleNextTestItem(suiteContainer); + userSettingsService.setLastTab(currentTabLabel); } - } else { + currentTabLabel = getCurrentTabLabel(); + userSettingsService.setLastTab(currentTabLabel); nextUrl.click(); scrollTo(nextUrl); $(testUrlSelector).not(nextUrl).removeClass('is-active'); } } else { - currentTest = findCurrentTest(currentLocation.split('/').pop()); - $firstElementInTest = currentTest.find('.url-name:not(.is-hidden)').find( - testUrlSelector).first(); - currentTest.addClass('is-expanded'); - $firstElementInTest.click(); - scrollTo($firstElementInTest); + currentTest = findCurrentTest(currentLocation.split('/').pop()); + $firstElementInTest = currentTest.find('.url-name:not(.is-hidden)').find( + testUrlSelector).first(); + currentTest.addClass('is-expanded'); + $firstElementInTest.click(); + scrollTo($firstElementInTest); } } function traverseTreeUp(currentItem, testContainer, suiteContainer, testUrlSelector) { - var previousTest, - currentLocation = window.location.hash, - $previousElement; + var previousTest; + var currentLocation = window.location.hash; + var $previousElement; + var currentTabLabel; if (!(ifRootPage(currentLocation, '/url/') || ifRootPage( currentLocation, '/test/') || ifRootPage(currentLocation, @@ -183,12 +184,19 @@ define(['angularAMD', 'userSettingsService'], function (angularAMD) { '.url-name:not(.is-hidden)').filter(':first').find( testUrlSelector); if (_.isEmpty(previousTest)) { - $previousElement = suiteContainer.find('.test-name'); - scrollTo($previousElement); - $previousElement.click(); - currentItem.parents('.url-name').removeClass('is-active'); - suiteContainer.addClass('is-expanded'); + if (!_.isEmpty($(suiteContainer).prevAll( + '.aside-report:not(.is-hidden)').first() + .find('.test-name'))) { + currentTabLabel = getCurrentTabLabel(); + $previousElement = suiteContainer.prevAll( + '.aside-report:not(.is-hidden)').first(); + handleStyling(testContainer, currentItem, $previousElement); + togglePrevTestItem(suiteContainer); + userSettingsService.setLastTab(currentTabLabel); + } } else { + currentTabLabel = getCurrentTabLabel(); + userSettingsService.setLastTab(currentTabLabel); scrollTo(previousTest); previousTest.click(); } @@ -208,13 +216,66 @@ define(['angularAMD', 'userSettingsService'], function (angularAMD) { } } - function toggleNextTest(currentTest) { - $(currentTest).nextAll('.aside-report:not(.is-hidden)') - .first() - .find('.test-name') - .click(); + function handleStyling(testContainer, currentItem, $element) { + testContainer.removeClass('is-active'); + currentItem.removeClass('is-active'); + $element.addClass('is-expanded'); + $element.children().first().addClass('is-active'); + scrollTo($element.find('.is-active')); } + function toggleNextTestItem(currentTest) { + $(currentTest).nextAll( + '.aside-report:not(.is-hidden)') + .first() + .find('.test-url') + .first() + .click(); + } + + function togglePrevTestItem(currentTest) { + $(currentTest).prevAll( + '.aside-report:not(.is-hidden)') + .first() + .find('.test-url') + .last() + .click(); + } + + function getCurrentTabLabel() { + return $('.nav-tabs > .nav-item').filter('.active').text().replace(/\s/g, ''); + } + + function clickOnTab() { + var currentTabLabel = userSettingsService.getLastTab(); + var $nextTestTabs = $('.nav-tabs').children(); + $nextTestTabs.each(function() { + if($(this).text().replace(/\s/g, '') === currentTabLabel) { + $(this).find('a').click(); + currentTabLabel = null; + } + }); + } + + //MutationObserver fires a callback every time something changes on the page + //and here it's used to click a tab before the page is actually rendered to get rid of flickering effect + var mutationObserver = new MutationObserver(callback); + + function callback(mutList) { + function findElement(element) { + if($(element.target).hasClass('nav-tabs')) { + clickOnTab(); + return true; + } + } + mutList.find(findElement); + } + + mutationObserver.observe(document, { + childList: true, + subtree: true, + }); + function ifRootPage(url, type) { return url.search(type) > 0; } @@ -252,4 +313,4 @@ define(['angularAMD', 'userSettingsService'], function (angularAMD) { } } } -}); +}); \ No newline at end of file diff --git a/report/src/main/webapp/app/services/userSettings.service.js b/report/src/main/webapp/app/services/userSettings.service.js index 943b52178..a9c724d36 100644 --- a/report/src/main/webapp/app/services/userSettings.service.js +++ b/report/src/main/webapp/app/services/userSettings.service.js @@ -28,13 +28,17 @@ define(['angularAMD', 'localStorageService'], function (angularAMD) { isScreenshotMaskVisible: isScreenshotMaskVisible, toggleScreenshotMask: toggleScreenshotMask, isFullSourceVisible: isFullSourceVisible, - toggleFullSource: toggleFullSource + toggleFullSource: toggleFullSource, + setLastTab: setLastTab, + getLastTab: getLastTab, }, SCREENSHOT_MASK_STORAGE_KEY = 'aet:settings.visibility.screenshotMask', FULL_SOURCE_MASK_STORAGE_KEY = 'aet:settings.visibility.fullSource', + USER_TAB_MASK_STORAGE_KEY = 'aet:settings.raport.lastTab', settings = { screenshotMaskVisible: true, - fullSourceMaskVisible: false + fullSourceMaskVisible: false, + lastUserTab: null, }; setupService(); @@ -45,6 +49,8 @@ define(['angularAMD', 'localStorageService'], function (angularAMD) { true); settings.fullSourceMaskVisible = getSetting(FULL_SOURCE_MASK_STORAGE_KEY, false); + settings.lastUserTab = getSetting(USER_TAB_MASK_STORAGE_KEY, + null); } function isScreenshotMaskVisible() { @@ -67,6 +73,14 @@ define(['angularAMD', 'localStorageService'], function (angularAMD) { return settings.fullSourceMaskVisible; } + function setLastTab(val) { + settings.userTab = val; + } + + function getLastTab() { + return settings.userTab; + } + /*************************************** *********** Private methods ********* ***************************************/