Loading core/modules/toolbar/tests/src/Nightwatch/Tests/toolbarApiTest.js 0 → 100644 +264 −0 Original line number Diff line number Diff line /** * @file * Tests of the existing Toolbar JS Api. */ module.exports = { '@tags': ['core'], before(browser) { browser .drupalInstall() .drupalInstallModule('breakpoint') .drupalInstallModule('toolbar') .drupalCreateUser({ name: 'user', password: '123', permissions: [ 'access site reports', 'access toolbar', 'administer menu', 'administer modules', 'administer site configuration', 'administer account settings', 'administer software updates', 'access content', 'administer permissions', 'administer users', ], }) .drupalLogin({ name: 'user', password: '123' }) .drupalRelativeURL('/') .waitForElementPresent('#toolbar-administration', 10000); }, beforeEach(browser) { // Set the resolution to the default desktop resolution. Ensure the default // toolbar is horizontal in headless mode. browser.resizeWindow(1920, 1080); // To clear active tab/tray from previous tests browser.execute(function () { localStorage.clear(); // Clear escapeAdmin url values. sessionStorage.clear(); }); browser.drupalRelativeURL('/'); }, after(browser) { browser.drupalUninstall(); }, 'Drupal.Toolbar.models': (browser) => { browser.execute( function () { const toReturn = {}; const { models } = Drupal.toolbar; toReturn.hasMenuModel = models.hasOwnProperty('menuModel'); toReturn.menuModelType = typeof models.menuModel === 'object'; toReturn.hasToolbarModel = models.hasOwnProperty('toolbarModel'); toReturn.toolbarModelType = typeof models.toolbarModel === 'object'; toReturn.toolbarModelActiveTab = models.toolbarModel.get('activeTab').id === 'toolbar-item-administration'; toReturn.toolbarModelActiveTray = models.toolbarModel.get('activeTray').id === 'toolbar-item-administration-tray'; toReturn.toolbarModelIsOriented = models.toolbarModel.get('isOriented') === true; toReturn.toolbarModelIsFixed = models.toolbarModel.get('isFixed') === true; toReturn.toolbarModelAreSubtreesLoaded = models.toolbarModel.get('areSubtreesLoaded') === false; toReturn.toolbarModelIsViewportOverflowConstrained = models.toolbarModel.get('isViewportOverflowConstrained') === false; toReturn.toolbarModelOrientation = models.toolbarModel.get('orientation') === 'horizontal'; toReturn.toolbarModelLocked = models.toolbarModel.get('locked') === null; toReturn.toolbarModelIsTrayToggleVisible = models.toolbarModel.get('isTrayToggleVisible') === true; toReturn.toolbarModelHeight = models.toolbarModel.get('height') === 79; toReturn.toolbarModelOffsetsBottom = models.toolbarModel.get('offsets').bottom === 0; toReturn.toolbarModelOffsetsLeft = models.toolbarModel.get('offsets').left === 0; toReturn.toolbarModelOffsetsRight = models.toolbarModel.get('offsets').right === 0; toReturn.toolbarModelOffsetsTop = models.toolbarModel.get('offsets').top === 79; toReturn.toolbarModelSubtrees = Object.keys(models.menuModel.get('subtrees')).length === 0; return toReturn; }, [], (result) => { const expectedTrue = { hasMenuModel: 'has menu model', menuModelType: 'menu model is an object', hasToolbarModel: 'has toolbar model', toolbarModelType: 'toolbar model is an object', toolbarModelActiveTab: 'get("activeTab") has expected result', toolbarModelActiveTray: 'get("activeTray") has expected result', toolbarModelIsOriented: 'get("isOriented") has expected result', toolbarModelIsFixed: 'get("isFixed") has expected result', toolbarModelAreSubtreesLoaded: 'get("areSubtreesLoaded") has expected result', toolbarModelIsViewportOverflowConstrained: 'get("isViewportOverflowConstrained") has expected result', toolbarModelOrientation: 'get("orientation") has expected result', toolbarModelLocked: 'get("locked") has expected result', toolbarModelIsTrayToggleVisible: 'get("isTrayToggleVisible") has expected result', toolbarModelHeight: 'get("height") has expected result', toolbarModelOffsetsBottom: 'get("offsets") bottom has expected result', toolbarModelOffsetsLeft: 'get("offsets") left has expected result', toolbarModelOffsetsRight: 'get("offsets") right has expected result', toolbarModelOffsetsTop: 'get("offsets") top has expected result', toolbarModelSubtrees: 'get("subtrees") has expected result', }; browser.assert.deepEqual( Object.keys(expectedTrue).sort(), Object.keys(result.value).sort(), 'Keys to check match', ); Object.keys(expectedTrue).forEach((property) => { browser.assert.equal( result.value[property], true, expectedTrue[property], ); }); }, ); }, 'Change tab': (browser) => { browser.execute( function () { const toReturn = {}; const { models } = Drupal.toolbar; toReturn.hasMenuModel = models.hasOwnProperty('menuModel'); toReturn.menuModelType = typeof models.menuModel === 'object'; toReturn.hasToolbarModel = models.hasOwnProperty('toolbarModel'); toReturn.toolbarModelType = typeof models.toolbarModel === 'object'; const tab = document.querySelector('#toolbar-item-user'); tab.dispatchEvent(new MouseEvent('click', { bubbles: true })); toReturn.toolbarModelChangedTab = models.toolbarModel.get('activeTab').id === 'toolbar-item-user'; toReturn.toolbarModelChangedTray = models.toolbarModel.get('activeTray').id === 'toolbar-item-user-tray'; return toReturn; }, [], (result) => { const expectedTrue = { hasMenuModel: 'has menu model', menuModelType: 'menu model is an object', hasToolbarModel: 'has toolbar model', toolbarModelType: 'toolbar model is an object', toolbarModelChangedTab: 'get("activeTab") has expected result', toolbarModelChangedTray: 'get("activeTray") has expected result', }; browser.assert.deepEqual( Object.keys(expectedTrue).sort(), Object.keys(result.value).sort(), 'Keys to check match', ); Object.keys(expectedTrue).forEach((property) => { browser.assert.equal( result.value[property], true, expectedTrue[property], ); }); }, ); }, 'Change orientation': (browser) => { browser.executeAsync( function (done) { const toReturn = {}; const { models } = Drupal.toolbar; const orientationToggle = document.querySelector( '#toolbar-item-administration-tray .toolbar-toggle-orientation button', ); toReturn.toolbarOrientation = models.toolbarModel.get('orientation') === 'horizontal'; orientationToggle.dispatchEvent( new MouseEvent('click', { bubbles: true }), ); setTimeout(() => { toReturn.toolbarChangeOrientation = models.toolbarModel.get('orientation') === 'vertical'; done(toReturn); }, 100); }, [], (result) => { const expectedTrue = { toolbarOrientation: 'get("orientation") has expected result', toolbarChangeOrientation: 'changing orientation has expected result', }; browser.assert.deepEqual( Object.keys(expectedTrue).sort(), Object.keys(result.value).sort(), 'Keys to check match', ); Object.keys(expectedTrue).forEach((property) => { browser.assert.equal( result.value[property], true, expectedTrue[property], ); }); }, ); }, 'Open submenu': (browser) => { browser.executeAsync( function (done) { const toReturn = {}; const { models } = Drupal.toolbar; Drupal.toolbar.models.toolbarModel.set('orientation', 'vertical'); toReturn.toolbarOrientation = models.toolbarModel.get('orientation') === 'vertical'; const manageTab = document.querySelector( '#toolbar-item-administration', ); Drupal.toolbar.models.toolbarModel.set('activeTab', manageTab); const menuDropdown = document.querySelector( '#toolbar-item-administration-tray button', ); menuDropdown.dispatchEvent(new MouseEvent('click', { bubbles: true })); setTimeout(() => { const statReportElement = document.querySelector( '#toolbar-link-system-status', ); toReturn.submenuItem = statReportElement.textContent === 'Status report'; done(toReturn); }, 100); }, [], (result) => { const expectedTrue = { toolbarOrientation: 'get("orientation") has expected result', submenuItem: 'opening submenu has expected result', }; browser.assert.deepEqual( Object.keys(expectedTrue).sort(), Object.keys(result.value).sort(), 'Keys to check match', ); Object.keys(expectedTrue).forEach((property) => { browser.assert.equal( result.value[property], true, expectedTrue[property], ); }); }, ); }, }; core/modules/toolbar/tests/src/Nightwatch/Tests/toolbarTest.js 0 → 100644 +379 −0 Original line number Diff line number Diff line /** * @file * Test the expected toolbar functionality. */ const itemAdministration = '#toolbar-item-administration'; const itemAdministrationTray = '#toolbar-item-administration-tray'; const adminOrientationButton = `${itemAdministrationTray} .toolbar-toggle-orientation button`; const itemUser = '#toolbar-item-user'; const itemUserTray = '#toolbar-item-user-tray'; const userOrientationBtn = `${itemUserTray} .toolbar-toggle-orientation button`; module.exports = { '@tags': ['core'], before(browser) { browser .drupalInstall() .drupalInstallModule('breakpoint') .drupalInstallModule('toolbar') .drupalCreateUser({ name: 'user', password: '123', permissions: [ 'access site reports', 'access toolbar', 'access administration pages', 'administer menu', 'administer modules', 'administer site configuration', 'administer account settings', 'administer software updates', 'access content', 'administer permissions', 'administer users', ], }) .drupalLogin({ name: 'user', password: '123' }) .drupalRelativeURL('/') .waitForElementPresent('#toolbar-administration', 10000); }, beforeEach(browser) { browser.resizeWindow(1920, 1080); browser.execute(function () { // To clear active tab/tray from previous tests. localStorage.clear(); // Clear escapeAdmin URL values. sessionStorage.clear(); }); browser.drupalRelativeURL('/'); }, after(browser) { browser.drupalUninstall(); }, 'Change tab': (browser) => { browser.waitForElementPresent(itemUserTray); browser.assert.not.cssClassPresent(itemUser, 'is-active'); browser.assert.not.cssClassPresent(itemUserTray, 'is-active'); browser.click(itemUser); browser.assert.cssClassPresent(itemUser, 'is-active'); browser.assert.cssClassPresent(itemUserTray, 'is-active'); }, 'Change orientation': (browser) => { browser.waitForElementPresent(adminOrientationButton); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-horizontal', ); browser.click(adminOrientationButton); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-vertical', ); browser.click(adminOrientationButton); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-horizontal', ); }, 'Toggle tray': (browser) => { browser.waitForElementPresent(itemUserTray); browser.click(itemUser); browser.assert.cssClassPresent(itemUserTray, 'is-active'); browser.click(itemUser); browser.assert.not.cssClassPresent(itemUserTray, 'is-active'); browser.click(itemUser); browser.assert.cssClassPresent(itemUserTray, 'is-active'); }, 'Toggle submenu and sub-submenu': (browser) => { browser.waitForElementPresent(adminOrientationButton); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-horizontal', ); browser.click(adminOrientationButton); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-vertical', ); browser.waitForElementPresent( '#toolbar-item-administration-tray li:nth-child(4) button', ); browser.assert.not.cssClassPresent( '#toolbar-item-administration-tray li:nth-child(4)', 'open', ); browser.assert.not.cssClassPresent( '#toolbar-item-administration-tray li:nth-child(4) button', 'open', ); browser.click('#toolbar-item-administration-tray li:nth-child(4) button'); browser.assert.cssClassPresent( '#toolbar-item-administration-tray li:nth-child(4)', 'open', ); browser.assert.cssClassPresent( '#toolbar-item-administration-tray li:nth-child(4) button', 'open', ); browser.expect .element('#toolbar-link-user-admin_index') .text.to.equal('People'); browser.expect .element('#toolbar-link-system-admin_config_system') .text.to.equal('System'); // Check sub-submenu. browser.waitForElementPresent( '#toolbar-item-administration-tray li.menu-item.level-2', ); browser.assert.not.cssClassPresent( '#toolbar-item-administration-tray li.menu-item.level-2', 'open', ); browser.assert.not.cssClassPresent( '#toolbar-item-administration-tray li.menu-item.level-2 button', 'open', ); browser.click( '#toolbar-item-administration-tray li.menu-item.level-2 button', ); browser.assert.cssClassPresent( '#toolbar-item-administration-tray li.menu-item.level-2', 'open', ); browser.assert.cssClassPresent( '#toolbar-item-administration-tray li.menu-item.level-2 button', 'open', ); browser.expect .element('#toolbar-link-entity-user-admin_form') .text.to.equal('Account settings'); }, 'Narrow toolbar width breakpoint': (browser) => { browser.waitForElementPresent(adminOrientationButton); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-horizontal', ); browser.assert.cssClassPresent( '#toolbar-administration', 'toolbar-oriented', ); browser.resizeWindow(263, 900); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-vertical', ); browser.assert.not.cssClassPresent(itemAdministration, 'toolbar-oriented'); }, 'Standard width toolbar breakpoint': (browser) => { browser.resizeWindow(1000, 900); browser.waitForElementPresent(adminOrientationButton); browser.assert.cssClassPresent('body', 'toolbar-fixed'); browser.resizeWindow(609, 900); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-vertical', ); browser.assert.not.cssClassPresent('body', 'toolbar-fixed'); }, 'Wide toolbar breakpoint': (browser) => { browser.waitForElementPresent(adminOrientationButton); browser.resizeWindow(975, 900); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-vertical', ); }, 'Back to site link': (browser) => { const escapeSelector = '[data-toolbar-escape-admin]'; browser.drupalRelativeURL('/user'); browser.drupalRelativeURL('/admin'); // Don't check the visibility as stark doesn't add the .path-admin class // to the <body> required to display the button. browser.assert.attributeContains(escapeSelector, 'href', '/user/2'); }, 'Aural view test: tray orientation': (browser) => { browser.waitForElementPresent( '#toolbar-item-administration-tray .toolbar-toggle-orientation button', ); browser.executeAsync( function (done) { Drupal.announce = done; const orientationButton = document.querySelector( '#toolbar-item-administration-tray .toolbar-toggle-orientation button', ); orientationButton.dispatchEvent( new MouseEvent('click', { bubbles: true }), ); }, (result) => { browser.assert.equal( result.value, 'Tray orientation changed to vertical.', ); }, ); browser.executeAsync( function (done) { Drupal.announce = done; const orientationButton = document.querySelector( '#toolbar-item-administration-tray .toolbar-toggle-orientation button', ); orientationButton.dispatchEvent( new MouseEvent('click', { bubbles: true }), ); }, (result) => { browser.assert.equal( result.value, 'Tray orientation changed to horizontal.', ); }, ); }, 'Aural view test: tray toggle': (browser) => { browser.executeAsync( function (done) { Drupal.announce = done; const $adminButton = jQuery('#toolbar-item-administration'); $adminButton.trigger('click'); }, (result) => { browser.assert.equal( result.value, 'Tray "Administration menu" closed.', ); }, ); browser.executeAsync( function (done) { Drupal.announce = done; const $adminButton = jQuery('#toolbar-item-administration'); $adminButton.trigger('click'); }, (result) => { browser.assert.equal( result.value, 'Tray "Administration menu" opened.', ); }, ); }, 'Toolbar event: drupalToolbarOrientationChange': (browser) => { browser.executeAsync( function (done) { jQuery(document).on( 'drupalToolbarOrientationChange', function (event, orientation) { done(orientation); }, ); const orientationButton = document.querySelector( '#toolbar-item-administration-tray .toolbar-toggle-orientation button', ); orientationButton.dispatchEvent( new MouseEvent('click', { bubbles: true }), ); }, (result) => { browser.assert.equal(result.value, 'vertical'); }, ); }, 'Toolbar event: drupalToolbarTabChange': (browser) => { browser.executeAsync( function (done) { jQuery(document).on('drupalToolbarTabChange', function (event, tab) { done(tab.id); }); jQuery('#toolbar-item-user').trigger('click'); }, (result) => { browser.assert.equal(result.value, 'toolbar-item-user'); }, ); }, 'Toolbar event: drupalToolbarTrayChange': (browser) => { browser.executeAsync( function (done) { const $adminButton = jQuery('#toolbar-item-administration'); // Hide the admin menu first, this event is not firing reliably // otherwise. $adminButton.trigger('click'); jQuery(document).on('drupalToolbarTrayChange', function (event, tray) { done(tray.id); }); $adminButton.trigger('click'); }, (result) => { browser.assert.equal(result.value, 'toolbar-item-administration-tray'); }, ); }, 'Locked toolbar vertical wide viewport': (browser) => { browser.resizeWindow(1000, 900); browser.waitForElementPresent(adminOrientationButton); // eslint-disable-next-line no-unused-expressions browser.expect.element(adminOrientationButton).to.be.visible; browser.resizeWindow(975, 900); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-vertical', ); // eslint-disable-next-line no-unused-expressions browser.expect.element(adminOrientationButton).to.not.be.visible; }, 'Settings are retained on refresh': (browser) => { browser.waitForElementPresent(itemUser); // Set user as active tab. browser.assert.not.cssClassPresent(itemUser, 'is-active'); browser.assert.not.cssClassPresent(itemUserTray, 'is-active'); browser.click(itemUser); // Check tab and tray are open. browser.assert.cssClassPresent(itemUser, 'is-active'); browser.assert.cssClassPresent(itemUserTray, 'is-active'); // Set orientation to vertical. browser.waitForElementPresent(userOrientationBtn); browser.assert.cssClassPresent( itemUserTray, 'is-active toolbar-tray-horizontal', ); browser.click(userOrientationBtn); browser.assert.cssClassPresent( itemUserTray, 'is-active toolbar-tray-vertical', ); browser.refresh(); // Check user tab is active. browser.assert.cssClassPresent(itemUser, 'is-active'); // Check tray is active and orientation is vertical. browser.assert.cssClassPresent( itemUserTray, 'is-active toolbar-tray-vertical', ); }, 'Check toolbar overlap with page content': (browser) => { browser.assert.cssClassPresent('body', 'toolbar-horizontal'); browser.execute( () => { const toolbar = document.querySelector('#toolbar-administration'); const nextElement = toolbar.nextElementSibling.getBoundingClientRect(); const tray = document .querySelector('#toolbar-item-administration-tray') .getBoundingClientRect(); // Page content should start after the toolbar height to not overlap. return nextElement.top > tray.top + tray.height; }, (result) => { browser.assert.equal( result.value, true, 'Toolbar and page content do not overlap', ); }, ); }, }; core/scripts/dev/commit-code-check.sh +1 −1 Original line number Diff line number Diff line Loading @@ -353,7 +353,7 @@ ############################################################################ ### JAVASCRIPT FILES ############################################################################ if [[ -f "$TOP_LEVEL/$FILE" ]] && [[ $FILE =~ \.js$ ]] && [[ ! $FILE =~ ^core/tests/Drupal/Nightwatch ]] && [[ ! $FILE =~ ^core/assets/vendor/jquery.ui/ui ]] && [[ ! $FILE =~ ^core/modules/ckeditor5/js/ckeditor5_plugins ]]; then if [[ -f "$TOP_LEVEL/$FILE" ]] && [[ $FILE =~ \.js$ ]] && [[ ! $FILE =~ ^core/tests/Drupal/Nightwatch ]] && [[ ! $FILE =~ /tests/src/Nightwatch/ ]] && [[ ! $FILE =~ ^core/assets/vendor/jquery.ui/ui ]] && [[ ! $FILE =~ ^core/modules/ckeditor5/js/ckeditor5_plugins ]]; then # Work out the root name of the JavaScript so we can ensure that the ES6 # version has been compiled correctly. if [[ $FILE =~ \.es6\.js$ ]]; then Loading core/tests/Drupal/Nightwatch/Commands/drupalInstallModule.js 0 → 100644 +26 −0 Original line number Diff line number Diff line /** * Install the given module. * * @param {string} module * The module machine name to enable. * @param {function} callback * A callback which will be called, when the module has been enabled. * @return {object} * The drupalInstallModule command. */ exports.command = function drupalInstallModule(module, callback) { const self = this; this.drupalLoginAsAdmin(() => { this.drupalRelativeURL('/admin/modules') .click(`input[data-drupal-selector="edit-modules-${module}-enable"]`) .click('input[data-drupal-selector="edit-submit"]') // Wait for the install message to show up. .waitForElementVisible('.system-modules', 10000); }).perform(() => { if (typeof callback === 'function') { callback.call(self); } }); return this; }; Loading
core/modules/toolbar/tests/src/Nightwatch/Tests/toolbarApiTest.js 0 → 100644 +264 −0 Original line number Diff line number Diff line /** * @file * Tests of the existing Toolbar JS Api. */ module.exports = { '@tags': ['core'], before(browser) { browser .drupalInstall() .drupalInstallModule('breakpoint') .drupalInstallModule('toolbar') .drupalCreateUser({ name: 'user', password: '123', permissions: [ 'access site reports', 'access toolbar', 'administer menu', 'administer modules', 'administer site configuration', 'administer account settings', 'administer software updates', 'access content', 'administer permissions', 'administer users', ], }) .drupalLogin({ name: 'user', password: '123' }) .drupalRelativeURL('/') .waitForElementPresent('#toolbar-administration', 10000); }, beforeEach(browser) { // Set the resolution to the default desktop resolution. Ensure the default // toolbar is horizontal in headless mode. browser.resizeWindow(1920, 1080); // To clear active tab/tray from previous tests browser.execute(function () { localStorage.clear(); // Clear escapeAdmin url values. sessionStorage.clear(); }); browser.drupalRelativeURL('/'); }, after(browser) { browser.drupalUninstall(); }, 'Drupal.Toolbar.models': (browser) => { browser.execute( function () { const toReturn = {}; const { models } = Drupal.toolbar; toReturn.hasMenuModel = models.hasOwnProperty('menuModel'); toReturn.menuModelType = typeof models.menuModel === 'object'; toReturn.hasToolbarModel = models.hasOwnProperty('toolbarModel'); toReturn.toolbarModelType = typeof models.toolbarModel === 'object'; toReturn.toolbarModelActiveTab = models.toolbarModel.get('activeTab').id === 'toolbar-item-administration'; toReturn.toolbarModelActiveTray = models.toolbarModel.get('activeTray').id === 'toolbar-item-administration-tray'; toReturn.toolbarModelIsOriented = models.toolbarModel.get('isOriented') === true; toReturn.toolbarModelIsFixed = models.toolbarModel.get('isFixed') === true; toReturn.toolbarModelAreSubtreesLoaded = models.toolbarModel.get('areSubtreesLoaded') === false; toReturn.toolbarModelIsViewportOverflowConstrained = models.toolbarModel.get('isViewportOverflowConstrained') === false; toReturn.toolbarModelOrientation = models.toolbarModel.get('orientation') === 'horizontal'; toReturn.toolbarModelLocked = models.toolbarModel.get('locked') === null; toReturn.toolbarModelIsTrayToggleVisible = models.toolbarModel.get('isTrayToggleVisible') === true; toReturn.toolbarModelHeight = models.toolbarModel.get('height') === 79; toReturn.toolbarModelOffsetsBottom = models.toolbarModel.get('offsets').bottom === 0; toReturn.toolbarModelOffsetsLeft = models.toolbarModel.get('offsets').left === 0; toReturn.toolbarModelOffsetsRight = models.toolbarModel.get('offsets').right === 0; toReturn.toolbarModelOffsetsTop = models.toolbarModel.get('offsets').top === 79; toReturn.toolbarModelSubtrees = Object.keys(models.menuModel.get('subtrees')).length === 0; return toReturn; }, [], (result) => { const expectedTrue = { hasMenuModel: 'has menu model', menuModelType: 'menu model is an object', hasToolbarModel: 'has toolbar model', toolbarModelType: 'toolbar model is an object', toolbarModelActiveTab: 'get("activeTab") has expected result', toolbarModelActiveTray: 'get("activeTray") has expected result', toolbarModelIsOriented: 'get("isOriented") has expected result', toolbarModelIsFixed: 'get("isFixed") has expected result', toolbarModelAreSubtreesLoaded: 'get("areSubtreesLoaded") has expected result', toolbarModelIsViewportOverflowConstrained: 'get("isViewportOverflowConstrained") has expected result', toolbarModelOrientation: 'get("orientation") has expected result', toolbarModelLocked: 'get("locked") has expected result', toolbarModelIsTrayToggleVisible: 'get("isTrayToggleVisible") has expected result', toolbarModelHeight: 'get("height") has expected result', toolbarModelOffsetsBottom: 'get("offsets") bottom has expected result', toolbarModelOffsetsLeft: 'get("offsets") left has expected result', toolbarModelOffsetsRight: 'get("offsets") right has expected result', toolbarModelOffsetsTop: 'get("offsets") top has expected result', toolbarModelSubtrees: 'get("subtrees") has expected result', }; browser.assert.deepEqual( Object.keys(expectedTrue).sort(), Object.keys(result.value).sort(), 'Keys to check match', ); Object.keys(expectedTrue).forEach((property) => { browser.assert.equal( result.value[property], true, expectedTrue[property], ); }); }, ); }, 'Change tab': (browser) => { browser.execute( function () { const toReturn = {}; const { models } = Drupal.toolbar; toReturn.hasMenuModel = models.hasOwnProperty('menuModel'); toReturn.menuModelType = typeof models.menuModel === 'object'; toReturn.hasToolbarModel = models.hasOwnProperty('toolbarModel'); toReturn.toolbarModelType = typeof models.toolbarModel === 'object'; const tab = document.querySelector('#toolbar-item-user'); tab.dispatchEvent(new MouseEvent('click', { bubbles: true })); toReturn.toolbarModelChangedTab = models.toolbarModel.get('activeTab').id === 'toolbar-item-user'; toReturn.toolbarModelChangedTray = models.toolbarModel.get('activeTray').id === 'toolbar-item-user-tray'; return toReturn; }, [], (result) => { const expectedTrue = { hasMenuModel: 'has menu model', menuModelType: 'menu model is an object', hasToolbarModel: 'has toolbar model', toolbarModelType: 'toolbar model is an object', toolbarModelChangedTab: 'get("activeTab") has expected result', toolbarModelChangedTray: 'get("activeTray") has expected result', }; browser.assert.deepEqual( Object.keys(expectedTrue).sort(), Object.keys(result.value).sort(), 'Keys to check match', ); Object.keys(expectedTrue).forEach((property) => { browser.assert.equal( result.value[property], true, expectedTrue[property], ); }); }, ); }, 'Change orientation': (browser) => { browser.executeAsync( function (done) { const toReturn = {}; const { models } = Drupal.toolbar; const orientationToggle = document.querySelector( '#toolbar-item-administration-tray .toolbar-toggle-orientation button', ); toReturn.toolbarOrientation = models.toolbarModel.get('orientation') === 'horizontal'; orientationToggle.dispatchEvent( new MouseEvent('click', { bubbles: true }), ); setTimeout(() => { toReturn.toolbarChangeOrientation = models.toolbarModel.get('orientation') === 'vertical'; done(toReturn); }, 100); }, [], (result) => { const expectedTrue = { toolbarOrientation: 'get("orientation") has expected result', toolbarChangeOrientation: 'changing orientation has expected result', }; browser.assert.deepEqual( Object.keys(expectedTrue).sort(), Object.keys(result.value).sort(), 'Keys to check match', ); Object.keys(expectedTrue).forEach((property) => { browser.assert.equal( result.value[property], true, expectedTrue[property], ); }); }, ); }, 'Open submenu': (browser) => { browser.executeAsync( function (done) { const toReturn = {}; const { models } = Drupal.toolbar; Drupal.toolbar.models.toolbarModel.set('orientation', 'vertical'); toReturn.toolbarOrientation = models.toolbarModel.get('orientation') === 'vertical'; const manageTab = document.querySelector( '#toolbar-item-administration', ); Drupal.toolbar.models.toolbarModel.set('activeTab', manageTab); const menuDropdown = document.querySelector( '#toolbar-item-administration-tray button', ); menuDropdown.dispatchEvent(new MouseEvent('click', { bubbles: true })); setTimeout(() => { const statReportElement = document.querySelector( '#toolbar-link-system-status', ); toReturn.submenuItem = statReportElement.textContent === 'Status report'; done(toReturn); }, 100); }, [], (result) => { const expectedTrue = { toolbarOrientation: 'get("orientation") has expected result', submenuItem: 'opening submenu has expected result', }; browser.assert.deepEqual( Object.keys(expectedTrue).sort(), Object.keys(result.value).sort(), 'Keys to check match', ); Object.keys(expectedTrue).forEach((property) => { browser.assert.equal( result.value[property], true, expectedTrue[property], ); }); }, ); }, };
core/modules/toolbar/tests/src/Nightwatch/Tests/toolbarTest.js 0 → 100644 +379 −0 Original line number Diff line number Diff line /** * @file * Test the expected toolbar functionality. */ const itemAdministration = '#toolbar-item-administration'; const itemAdministrationTray = '#toolbar-item-administration-tray'; const adminOrientationButton = `${itemAdministrationTray} .toolbar-toggle-orientation button`; const itemUser = '#toolbar-item-user'; const itemUserTray = '#toolbar-item-user-tray'; const userOrientationBtn = `${itemUserTray} .toolbar-toggle-orientation button`; module.exports = { '@tags': ['core'], before(browser) { browser .drupalInstall() .drupalInstallModule('breakpoint') .drupalInstallModule('toolbar') .drupalCreateUser({ name: 'user', password: '123', permissions: [ 'access site reports', 'access toolbar', 'access administration pages', 'administer menu', 'administer modules', 'administer site configuration', 'administer account settings', 'administer software updates', 'access content', 'administer permissions', 'administer users', ], }) .drupalLogin({ name: 'user', password: '123' }) .drupalRelativeURL('/') .waitForElementPresent('#toolbar-administration', 10000); }, beforeEach(browser) { browser.resizeWindow(1920, 1080); browser.execute(function () { // To clear active tab/tray from previous tests. localStorage.clear(); // Clear escapeAdmin URL values. sessionStorage.clear(); }); browser.drupalRelativeURL('/'); }, after(browser) { browser.drupalUninstall(); }, 'Change tab': (browser) => { browser.waitForElementPresent(itemUserTray); browser.assert.not.cssClassPresent(itemUser, 'is-active'); browser.assert.not.cssClassPresent(itemUserTray, 'is-active'); browser.click(itemUser); browser.assert.cssClassPresent(itemUser, 'is-active'); browser.assert.cssClassPresent(itemUserTray, 'is-active'); }, 'Change orientation': (browser) => { browser.waitForElementPresent(adminOrientationButton); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-horizontal', ); browser.click(adminOrientationButton); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-vertical', ); browser.click(adminOrientationButton); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-horizontal', ); }, 'Toggle tray': (browser) => { browser.waitForElementPresent(itemUserTray); browser.click(itemUser); browser.assert.cssClassPresent(itemUserTray, 'is-active'); browser.click(itemUser); browser.assert.not.cssClassPresent(itemUserTray, 'is-active'); browser.click(itemUser); browser.assert.cssClassPresent(itemUserTray, 'is-active'); }, 'Toggle submenu and sub-submenu': (browser) => { browser.waitForElementPresent(adminOrientationButton); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-horizontal', ); browser.click(adminOrientationButton); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-vertical', ); browser.waitForElementPresent( '#toolbar-item-administration-tray li:nth-child(4) button', ); browser.assert.not.cssClassPresent( '#toolbar-item-administration-tray li:nth-child(4)', 'open', ); browser.assert.not.cssClassPresent( '#toolbar-item-administration-tray li:nth-child(4) button', 'open', ); browser.click('#toolbar-item-administration-tray li:nth-child(4) button'); browser.assert.cssClassPresent( '#toolbar-item-administration-tray li:nth-child(4)', 'open', ); browser.assert.cssClassPresent( '#toolbar-item-administration-tray li:nth-child(4) button', 'open', ); browser.expect .element('#toolbar-link-user-admin_index') .text.to.equal('People'); browser.expect .element('#toolbar-link-system-admin_config_system') .text.to.equal('System'); // Check sub-submenu. browser.waitForElementPresent( '#toolbar-item-administration-tray li.menu-item.level-2', ); browser.assert.not.cssClassPresent( '#toolbar-item-administration-tray li.menu-item.level-2', 'open', ); browser.assert.not.cssClassPresent( '#toolbar-item-administration-tray li.menu-item.level-2 button', 'open', ); browser.click( '#toolbar-item-administration-tray li.menu-item.level-2 button', ); browser.assert.cssClassPresent( '#toolbar-item-administration-tray li.menu-item.level-2', 'open', ); browser.assert.cssClassPresent( '#toolbar-item-administration-tray li.menu-item.level-2 button', 'open', ); browser.expect .element('#toolbar-link-entity-user-admin_form') .text.to.equal('Account settings'); }, 'Narrow toolbar width breakpoint': (browser) => { browser.waitForElementPresent(adminOrientationButton); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-horizontal', ); browser.assert.cssClassPresent( '#toolbar-administration', 'toolbar-oriented', ); browser.resizeWindow(263, 900); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-vertical', ); browser.assert.not.cssClassPresent(itemAdministration, 'toolbar-oriented'); }, 'Standard width toolbar breakpoint': (browser) => { browser.resizeWindow(1000, 900); browser.waitForElementPresent(adminOrientationButton); browser.assert.cssClassPresent('body', 'toolbar-fixed'); browser.resizeWindow(609, 900); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-vertical', ); browser.assert.not.cssClassPresent('body', 'toolbar-fixed'); }, 'Wide toolbar breakpoint': (browser) => { browser.waitForElementPresent(adminOrientationButton); browser.resizeWindow(975, 900); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-vertical', ); }, 'Back to site link': (browser) => { const escapeSelector = '[data-toolbar-escape-admin]'; browser.drupalRelativeURL('/user'); browser.drupalRelativeURL('/admin'); // Don't check the visibility as stark doesn't add the .path-admin class // to the <body> required to display the button. browser.assert.attributeContains(escapeSelector, 'href', '/user/2'); }, 'Aural view test: tray orientation': (browser) => { browser.waitForElementPresent( '#toolbar-item-administration-tray .toolbar-toggle-orientation button', ); browser.executeAsync( function (done) { Drupal.announce = done; const orientationButton = document.querySelector( '#toolbar-item-administration-tray .toolbar-toggle-orientation button', ); orientationButton.dispatchEvent( new MouseEvent('click', { bubbles: true }), ); }, (result) => { browser.assert.equal( result.value, 'Tray orientation changed to vertical.', ); }, ); browser.executeAsync( function (done) { Drupal.announce = done; const orientationButton = document.querySelector( '#toolbar-item-administration-tray .toolbar-toggle-orientation button', ); orientationButton.dispatchEvent( new MouseEvent('click', { bubbles: true }), ); }, (result) => { browser.assert.equal( result.value, 'Tray orientation changed to horizontal.', ); }, ); }, 'Aural view test: tray toggle': (browser) => { browser.executeAsync( function (done) { Drupal.announce = done; const $adminButton = jQuery('#toolbar-item-administration'); $adminButton.trigger('click'); }, (result) => { browser.assert.equal( result.value, 'Tray "Administration menu" closed.', ); }, ); browser.executeAsync( function (done) { Drupal.announce = done; const $adminButton = jQuery('#toolbar-item-administration'); $adminButton.trigger('click'); }, (result) => { browser.assert.equal( result.value, 'Tray "Administration menu" opened.', ); }, ); }, 'Toolbar event: drupalToolbarOrientationChange': (browser) => { browser.executeAsync( function (done) { jQuery(document).on( 'drupalToolbarOrientationChange', function (event, orientation) { done(orientation); }, ); const orientationButton = document.querySelector( '#toolbar-item-administration-tray .toolbar-toggle-orientation button', ); orientationButton.dispatchEvent( new MouseEvent('click', { bubbles: true }), ); }, (result) => { browser.assert.equal(result.value, 'vertical'); }, ); }, 'Toolbar event: drupalToolbarTabChange': (browser) => { browser.executeAsync( function (done) { jQuery(document).on('drupalToolbarTabChange', function (event, tab) { done(tab.id); }); jQuery('#toolbar-item-user').trigger('click'); }, (result) => { browser.assert.equal(result.value, 'toolbar-item-user'); }, ); }, 'Toolbar event: drupalToolbarTrayChange': (browser) => { browser.executeAsync( function (done) { const $adminButton = jQuery('#toolbar-item-administration'); // Hide the admin menu first, this event is not firing reliably // otherwise. $adminButton.trigger('click'); jQuery(document).on('drupalToolbarTrayChange', function (event, tray) { done(tray.id); }); $adminButton.trigger('click'); }, (result) => { browser.assert.equal(result.value, 'toolbar-item-administration-tray'); }, ); }, 'Locked toolbar vertical wide viewport': (browser) => { browser.resizeWindow(1000, 900); browser.waitForElementPresent(adminOrientationButton); // eslint-disable-next-line no-unused-expressions browser.expect.element(adminOrientationButton).to.be.visible; browser.resizeWindow(975, 900); browser.assert.cssClassPresent( itemAdministrationTray, 'is-active toolbar-tray-vertical', ); // eslint-disable-next-line no-unused-expressions browser.expect.element(adminOrientationButton).to.not.be.visible; }, 'Settings are retained on refresh': (browser) => { browser.waitForElementPresent(itemUser); // Set user as active tab. browser.assert.not.cssClassPresent(itemUser, 'is-active'); browser.assert.not.cssClassPresent(itemUserTray, 'is-active'); browser.click(itemUser); // Check tab and tray are open. browser.assert.cssClassPresent(itemUser, 'is-active'); browser.assert.cssClassPresent(itemUserTray, 'is-active'); // Set orientation to vertical. browser.waitForElementPresent(userOrientationBtn); browser.assert.cssClassPresent( itemUserTray, 'is-active toolbar-tray-horizontal', ); browser.click(userOrientationBtn); browser.assert.cssClassPresent( itemUserTray, 'is-active toolbar-tray-vertical', ); browser.refresh(); // Check user tab is active. browser.assert.cssClassPresent(itemUser, 'is-active'); // Check tray is active and orientation is vertical. browser.assert.cssClassPresent( itemUserTray, 'is-active toolbar-tray-vertical', ); }, 'Check toolbar overlap with page content': (browser) => { browser.assert.cssClassPresent('body', 'toolbar-horizontal'); browser.execute( () => { const toolbar = document.querySelector('#toolbar-administration'); const nextElement = toolbar.nextElementSibling.getBoundingClientRect(); const tray = document .querySelector('#toolbar-item-administration-tray') .getBoundingClientRect(); // Page content should start after the toolbar height to not overlap. return nextElement.top > tray.top + tray.height; }, (result) => { browser.assert.equal( result.value, true, 'Toolbar and page content do not overlap', ); }, ); }, };
core/scripts/dev/commit-code-check.sh +1 −1 Original line number Diff line number Diff line Loading @@ -353,7 +353,7 @@ ############################################################################ ### JAVASCRIPT FILES ############################################################################ if [[ -f "$TOP_LEVEL/$FILE" ]] && [[ $FILE =~ \.js$ ]] && [[ ! $FILE =~ ^core/tests/Drupal/Nightwatch ]] && [[ ! $FILE =~ ^core/assets/vendor/jquery.ui/ui ]] && [[ ! $FILE =~ ^core/modules/ckeditor5/js/ckeditor5_plugins ]]; then if [[ -f "$TOP_LEVEL/$FILE" ]] && [[ $FILE =~ \.js$ ]] && [[ ! $FILE =~ ^core/tests/Drupal/Nightwatch ]] && [[ ! $FILE =~ /tests/src/Nightwatch/ ]] && [[ ! $FILE =~ ^core/assets/vendor/jquery.ui/ui ]] && [[ ! $FILE =~ ^core/modules/ckeditor5/js/ckeditor5_plugins ]]; then # Work out the root name of the JavaScript so we can ensure that the ES6 # version has been compiled correctly. if [[ $FILE =~ \.es6\.js$ ]]; then Loading
core/tests/Drupal/Nightwatch/Commands/drupalInstallModule.js 0 → 100644 +26 −0 Original line number Diff line number Diff line /** * Install the given module. * * @param {string} module * The module machine name to enable. * @param {function} callback * A callback which will be called, when the module has been enabled. * @return {object} * The drupalInstallModule command. */ exports.command = function drupalInstallModule(module, callback) { const self = this; this.drupalLoginAsAdmin(() => { this.drupalRelativeURL('/admin/modules') .click(`input[data-drupal-selector="edit-modules-${module}-enable"]`) .click('input[data-drupal-selector="edit-submit"]') // Wait for the install message to show up. .waitForElementVisible('.system-modules', 10000); }).perform(() => { if (typeof callback === 'function') { callback.call(self); } }); return this; };