jenkins-bot has submitted this change and it was merged. Change subject: Don't pull in initialisation code. ......................................................................
Don't pull in initialisation code. In Special:JavaScriptTest/qunit/plain there is no page to construct Thus a lot of the code in mobile.startup init.js was causing side effects and it really shouldn't be pulled into the test suite. Separating our initialisation scripts from our classes allows us to use them in places over than Minerva and test them better in isolation without incurring side effects. Changes: * EditorOverlayBase and classes that inherit from it must be passed an instance of PageApi * TalkSectionAddOverlay, TalkOverlay, TalkSectionOverlay now must be passed an instance of PageApi * Skins can now be initialized without passing tabletModules as an option * Rename of mobile.head to more meaningful skins.minerva.scripts.top * Rename all ResourceLoader modules which have initialisation code in them to have a skins.minerva prefix. * Make it clear that any module defined with a mobile prefix should not have any side effects * Leave module names that impact anonymous users intact until cache clears (note mobile.talk and mobile.newusers only impact logged in users so are cache exempt) * Update test for toast code now that it's not passing simply due to side-effects of pulling in styles that should not be pulled in Dependency: I1e19e6df6f36ec6d59630d651ca7f1e74cb16d30 Dependency: Iaef2e7a0706b0ec6c470ab43692c48b96a74b403 Bug: T103991 Bug: T101795 Change-Id: If37a623f1571645a040c10fc7c5304c7ee0fd332 --- M includes/Resources.php M includes/skins/SkinMinerva.php M includes/skins/SkinMinervaBeta.php M resources/mobile.editor.common/EditorOverlayBase.js R resources/mobile.issues/cleanuptemplates.js R resources/mobile.references/references.js M resources/mobile.startup/Skin.js M resources/mobile.talk.overlays/TalkOverlay.js M resources/mobile.talk.overlays/TalkSectionAddOverlay.js M resources/mobile.talk.overlays/TalkSectionOverlay.js R resources/mobile.toggle/toggle.js R resources/mobile.toggle/toggle.less A resources/skins.minerva.alpha.scripts/quickLookup.js R resources/skins.minerva.beta.scripts/fontchanger.js R resources/skins.minerva.categories/init.js R resources/skins.minerva.editor/init.js R resources/skins.minerva.newusers/init.js R resources/skins.minerva.notifications/init.js R resources/skins.minerva.scripts.top/init.js M resources/skins.minerva.scripts/init.js R resources/skins.minerva.scripts/mobileRedirect.js R resources/skins.minerva.scripts/preInit.js R resources/skins.minerva.scripts/search.js R resources/skins.minerva.tablet.scripts/toc.js R resources/skins.minerva.talk/init.js R resources/skins.minerva.talk/talk.less A resources/skins.minerva.toggling/init.js R resources/skins.minerva.watchstar/init.js M tests/browser/features/step_definitions/notification_steps.rb R tests/qunit/mobile.issues/test_cleanuptemplates.js R tests/qunit/mobile.references/test_references.js M tests/qunit/mobile.talk.overlays/test_TalkOverlay.js M tests/qunit/mobile.talk.overlays/test_TalkSectionOverlay.js R tests/qunit/mobile.toggle/test_toggle.js M tests/qunit/mobile.watchstar/test_Watchstar.js 35 files changed, 437 insertions(+), 264 deletions(-) Approvals: Bmansurov: Looks good to me, approved jenkins-bot: Verified diff --git a/includes/Resources.php b/includes/Resources.php index b2ee74b..5c4d095 100644 --- a/includes/Resources.php +++ b/includes/Resources.php @@ -217,6 +217,12 @@ ), ); +/* +Any modules defined here should come without side effects. +A module prefixed with 'mobile.' should be reusable in any context e.g. +any skin. If you are writing an initialisation script please define it with +the skin.minerva. prefix along with all the others below. +*/ $wgResourceModules = array_merge( $wgResourceModules, array( 'mobile.modules' => $wgMFResourceFileModuleBoilerplate + array( 'scripts' => array( @@ -249,17 +255,6 @@ 'resources/mobile.context/context.js', ), ), - 'mobile.browse' => $wgMFResourceFileModuleBoilerplate + array( - 'dependencies' => array( - 'mobile.loggingSchemas' - ), - 'scripts' => array( - 'resources/mobile.browse/init.js', - ), - 'styles' => array( - 'resources/mobile.browse/tags.less', - ) - ), 'mobile.browser' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( 'mobile.view', @@ -271,6 +266,7 @@ 'mobile.mainMenu' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( 'mobile.view', + 'mobile.browser', ), 'position' => 'bottom', 'styles' => array( @@ -373,6 +369,7 @@ 'dependencies' => array( 'mobile.infiniteScroll', 'mobile.pagelist.scripts', + 'mobile.modifiedBar', ), 'scripts' => array( 'resources/mobile.watchlist/WatchListApi.js', @@ -388,7 +385,6 @@ ), 'scripts' => array( 'resources/mobile.toc/TableOfContents.js', - 'resources/mobile.toc/init.js', ), 'styles' => array( 'resources/mobile.toc/toc.less', @@ -413,7 +409,6 @@ 'mobile.settings' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( - 'mobile.head', 'jquery.cookie', 'mediawiki.storage', ), @@ -425,7 +420,9 @@ // FIXME: Split this module into different features. 'mobile.startup' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( - 'mobile.head', + 'mobile.context', + 'mobile.browser', + 'mobile.oo', 'mobile.user', 'mediawiki.api', 'mobile.settings', @@ -467,7 +464,6 @@ 'resources/mobile.startup/Skin.js', 'resources/mobile.startup/Schema.js', 'resources/mobile.startup/util.js', - 'resources/mobile.startup/init.js', ), 'position' => 'bottom', ), @@ -486,43 +482,29 @@ 'mediawiki.user', 'mediawiki.storage', // Ensure M.define exists - 'mobile.head', + 'mobile.modules', ), 'scripts' => array( 'resources/mobile.user/user.js', ), ), - 'mobile.editor' => $wgMFResourceParsedMessageModuleBoilerplate + array( + // FIXME: Remove when cache clears + 'mobile.editor' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( - 'mobile.startup', - 'mobile.drawers', - 'mediawiki.ui.input', - 'mobile.settings', - 'mobile.toast', - // Let's ensure toggle styles have loaded before adding edit section links - 'mobile.toggling', - // Route needs moduleLoader - 'mobile.overlays', - 'mediawiki.jqueryMsg', + 'skins.minerva.editor', ), - 'messages' => array( - // editor.js - 'mobile-frontend-editor-disabled', - 'mobile-frontend-editor-unavailable', - 'mobile-frontend-editor-uploadenable', - 'mobile-frontend-editor-blocked-info-loggedin' => array( 'parse' ), - 'mobile-frontend-editor-cta', - 'mobile-frontend-editor-anon', - 'mobile-frontend-editor-undo-unsupported', - // edit link - 'mobile-frontend-editor-edit', - 'mobile-frontend-editor-redlink-create', - 'mobile-frontend-editor-redlink-leave', - 'mobile-frontend-editor-redlink-explain' => array( 'parse' ), + ), + // FIXME: Remove when cache clears + 'mobile.browse' => $wgMFResourceFileModuleBoilerplate + array( + 'dependencies' => array( + 'skins.minerva.browse', ), - 'scripts' => array( - 'resources/mobile.editor/init.js', + ), + // FIXME: Remove when cache clears + 'mobile.toggling' => $wgMFResourceFileModuleBoilerplate + array( + 'dependencies' => array( + 'skins.minerva.toggling', ), ), @@ -688,26 +670,6 @@ ) ), - 'mobile.talk' => $wgMFResourceFileModuleBoilerplate + array( - 'dependencies' => array( - 'mobile.overlays', - ), - 'styles' => array( - 'resources/mobile.talk/talk.less', - ), - 'scripts' => array( - 'resources/mobile.talk/init.js', - ), - 'messages' => array( - 'mobile-frontend-talk-overlay-header', - 'mobile-frontend-talk-add-overlay-submit', - 'mobile-frontend-editor-licensing', - 'mobile-frontend-editor-licensing-with-terms', - // FIXME: Remove after cache is cleared - 'talk', - ), - ), - 'mobile.search' => $wgMFResourceParsedMessageModuleBoilerplate + array( 'dependencies' => array( 'mobile.pagelist.scripts', @@ -720,7 +682,6 @@ 'scripts' => array( 'resources/mobile.search/SearchOverlay.js', 'resources/mobile.search/MobileWebSearchLogger.js', - 'resources/mobile.search/init.js', ), 'templates' => array( 'SearchOverlay.hogan' => 'resources/mobile.search/SearchOverlay.hogan', @@ -769,7 +730,6 @@ 'mobile.talk.overlays' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( - 'mobile.talk', 'mediawiki.ui.anchor', 'mobile.editor.common', ), @@ -876,16 +836,6 @@ ), ), - 'mobile.categories' => $wgMFResourceFileModuleBoilerplate + array( - 'dependencies' => array( - 'mobile.overlays', - 'mobile.loggingSchemas', - ), - 'scripts' => array( - 'resources/mobile.categories/init.js', - ), - ), - 'mobile.categories.overlays' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( 'mediawiki.Title', @@ -988,22 +938,6 @@ ), ), - // This module remembers that desktop site is your preference for viewing on a mobile phone - 'mobile.redirect' => $wgMFResourceFileModuleBoilerplate + array( - 'dependencies' => array( - 'mobile.startup', - 'mobile.toast', - 'mobile.settings', - ), - 'scripts' => array( - 'resources/mobile.redirect/init.js', - ), - 'messages' => array( - // mf-stop-mobile-redirect.js - 'mobile-frontend-cookies-required', - ), - ), - 'mobile.references' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( 'mobile.drawers', @@ -1020,20 +954,21 @@ ), 'scripts' => array( 'resources/mobile.references/ReferencesDrawer.js', - 'resources/mobile.references/init.js', + 'resources/mobile.references/references.js', ), ), - 'mobile.toggling' => $wgMFResourceFileModuleBoilerplate + array( + 'mobile.toggle' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( - 'mobile.startup', 'mobile.settings', + // uses util.js + 'mobile.startup', ), 'styles' => array( - 'resources/mobile.toggling/toggle.less', + 'resources/mobile.toggle/toggle.less', ), 'scripts' => array( - 'resources/mobile.toggling/init.js', + 'resources/mobile.toggle/toggle.js', ), ), @@ -1053,23 +988,6 @@ ), 'templates' => array( 'PointerOverlay.hogan' => 'resources/mobile.contentOverlays/PointerOverlay.hogan', - ), - ), - - 'mobile.newusers' => $wgMFResourceFileModuleBoilerplate + array( - 'dependencies' => array( - 'mobile.editor', - 'mobile.contentOverlays', - 'mobile.loggingSchemas', - ), - 'scripts' => array( - 'resources/mobile.newusers/init.js', - ), - 'messages' => array( - // newbieEditor.js - 'mobile-frontend-editor-tutorial-summary', - 'mobile-frontend-editor-tutorial-confirm', - 'mobile-frontend-editor-tutorial-cancel', ), ), @@ -1099,21 +1017,10 @@ ), ), - 'mobile.watchstar.init' => $wgMFResourceFileModuleBoilerplate + array( + // FIXME: Remove when cache clears. + 'mobile.watchstar.init' => array( 'dependencies' => array( - 'mobile.watchstar', - ), - 'scripts' => array( - 'resources/mobile.watchstar.init/init.js', - ), - 'messages' => array( - 'watchthispage', - 'unwatchthispage', - // mf-watchstar.js - 'mobile-frontend-watchlist-add', - 'mobile-frontend-watchlist-removed', - 'mobile-frontend-watchlist-cta', - 'mobile-frontend-watchlist-please-wait', + 'skins.minerva.watchstar', ), ), @@ -1163,7 +1070,7 @@ ), 'scripts' => array( 'resources/mobile.issues/CleanupOverlay.js', - 'resources/mobile.issues/init.js', + 'resources/mobile.issues/cleanuptemplates.js', ), 'messages' => array( // issues.js @@ -1284,17 +1191,6 @@ 'position' => 'top', ), - 'mobile.fontchanger.init' => $wgMFResourceFileModuleBoilerplate + array( - 'dependencies' => array( - 'mobile.startup', - 'mobile.settings', - ), - 'scripts' => array( - 'resources/mobile.fontchanger.init/init.js', - ), - 'position' => 'top', - ), - 'mobile.fontchanger' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( 'mobile.startup', @@ -1354,14 +1250,15 @@ * Extension:Echo related modules */ $wgMobileEchoModules = array( - 'mobile.notifications' => $wgMFResourceFileModuleBoilerplate + array( + 'skins.minerva.notifications' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( 'mobile.overlays', + 'skins.minerva.scripts', 'mediawiki.ui.anchor', 'mobile.loggingSchemas', ), 'scripts' => array( - 'resources/mobile.notifications/init.js', + 'resources/skins.minerva.notifications/init.js', ), ), @@ -1648,9 +1545,14 @@ // These modules are the gateways to all other modules and will ensure the other modules get loaded // on the page. $wgMinervaBootstrapModules = array( - // Important: This module is loaded on both mobile and desktop skin - // This JavaScript is loaded at the top of the page so be cautious what you put in it. + //FIXME: Remove when cache has cleared. Use skins.minerva.head instead 'mobile.head' => $wgMFResourceFileModuleBoilerplate + array( + 'dependencies' => array( + 'skins.minerva.scripts.top', + ), + ), + + 'skins.minerva.scripts.top' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( 'mobile.modifiedBar', 'mobile.mainMenu', @@ -1664,7 +1566,7 @@ 'mobile.context', ), 'scripts' => array( - 'resources/mobile.head/init.js', + 'resources/skins.minerva.scripts.top/init.js', ), 'messages' => array( // lastEdited.js @@ -1682,37 +1584,169 @@ // By mode. This should only ever be loaded in Minerva skin. 'skins.minerva.scripts' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( + 'skins.minerva.scripts.top', 'mobile.startup', + 'mobile.mainMenu', 'mobile.loggingSchemas', 'skins.minerva.icons.images.js', - // Feature modules that should be loaded in stable. - // These modules should only setup routes/events or - // load code under certain conditions. 'mobile.issues', 'mobile.search', 'mobile.references', - 'mobile.redirect', 'mobile.betaoptin', + 'mobile.toast', + 'mobile.settings', ), 'scripts' => array( + // FIXME: Merge preInit and init files. + 'resources/skins.minerva.scripts/preInit.js', 'resources/skins.minerva.scripts/init.js', 'resources/skins.minerva.scripts/initLogging.js', + 'resources/skins.minerva.scripts/mobileRedirect.js', + 'resources/skins.minerva.scripts/search.js', + ), + 'messages' => array( + // mf-stop-mobile-redirect.js + 'mobile-frontend-cookies-required', ), ), + + 'skins.minerva.browse' => $wgMFResourceFileModuleBoilerplate + array( + 'dependencies' => array( + 'mobile.loggingSchemas' + ), + 'scripts' => array( + 'resources/mobile.browse/init.js', + ), + 'styles' => array( + 'resources/mobile.browse/tags.less', + ) + ), + + 'skins.minerva.newusers' => $wgMFResourceFileModuleBoilerplate + array( + 'dependencies' => array( + 'mobile.editor', + 'mobile.contentOverlays', + 'mobile.loggingSchemas', + ), + 'scripts' => array( + 'resources/skins.minerva.newusers/init.js', + ), + 'messages' => array( + // newbieEditor.js + 'mobile-frontend-editor-tutorial-summary', + 'mobile-frontend-editor-tutorial-confirm', + 'mobile-frontend-editor-tutorial-cancel', + ), + ), + + 'skins.minerva.editor' => $wgMFResourceParsedMessageModuleBoilerplate + array( + 'dependencies' => array( + 'skins.minerva.scripts', + 'mobile.drawers', + 'mediawiki.ui.input', + 'mobile.settings', + 'mobile.toast', + // Let's ensure toggle styles have loaded before adding edit section links + 'skins.minerva.toggling', + // Route needs moduleLoader + 'mobile.overlays', + 'mediawiki.jqueryMsg', + ), + 'messages' => array( + // editor.js + 'mobile-frontend-editor-disabled', + 'mobile-frontend-editor-unavailable', + 'mobile-frontend-editor-uploadenable', + 'mobile-frontend-editor-blocked-info-loggedin' => array( 'parse' ), + 'mobile-frontend-editor-cta', + 'mobile-frontend-editor-anon', + 'mobile-frontend-editor-undo-unsupported', + // edit link + 'mobile-frontend-editor-edit', + 'mobile-frontend-editor-redlink-create', + 'mobile-frontend-editor-redlink-leave', + 'mobile-frontend-editor-redlink-explain' => array( 'parse' ), + ), + 'scripts' => array( + 'resources/skins.minerva.editor/init.js', + ), + ), + + 'skins.minerva.categories' => $wgMFResourceFileModuleBoilerplate + array( + 'dependencies' => array( + 'mobile.overlays', + 'mobile.loggingSchemas', + ), + 'scripts' => array( + 'resources/skins.minerva.categories/init.js', + ), + ), + + 'skins.minerva.talk' => $wgMFResourceFileModuleBoilerplate + array( + 'dependencies' => array( + 'skins.minerva.scripts', + 'mobile.overlays', + ), + 'styles' => array( + 'resources/skins.minerva.talk/talk.less', + ), + 'scripts' => array( + 'resources/skins.minerva.talk/init.js', + ), + 'messages' => array( + 'mobile-frontend-talk-overlay-header', + 'mobile-frontend-talk-add-overlay-submit', + 'mobile-frontend-editor-licensing', + 'mobile-frontend-editor-licensing-with-terms', + // FIXME: Remove after cache is cleared + 'talk', + ), + ), + + 'skins.minerva.toggling' => $wgMFResourceParsedMessageModuleBoilerplate + array( + 'dependencies' => array( + 'mobile.toggle', + 'skins.minerva.scripts', + ), + 'scripts' => array( + 'resources/skins.minerva.toggling/init.js', + ), + ), + + 'skins.minerva.watchstar' => $wgMFResourceFileModuleBoilerplate + array( + 'dependencies' => array( + 'mobile.watchstar', + 'skins.minerva.scripts', + ), + 'scripts' => array( + 'resources/skins.minerva.watchstar/init.js', + ), + 'messages' => array( + 'watchthispage', + 'unwatchthispage', + // mf-watchstar.js + 'mobile-frontend-watchlist-add', + 'mobile-frontend-watchlist-removed', + 'mobile-frontend-watchlist-cta', + 'mobile-frontend-watchlist-please-wait', + ), + ), + // By mode. This should only ever be loaded in Minerva skin. 'skins.minerva.beta.scripts' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( 'skins.minerva.scripts', + 'mobile.settings', // Feature modules that should be loaded in beta should be listed below here. // These modules should only setup routes/events or // load code under certain conditions. 'mobile.bannerImage', 'mobile.search.beta', - 'mobile.fontchanger.init', ), 'scripts' => array( 'resources/skins.minerva.beta.scripts/bannerImage.js', 'resources/skins.minerva.beta.scripts/commonsCategory.js', + 'resources/skins.minerva.beta.scripts/fontchanger.js', ), 'messages' => array( 'mobile-frontend-commons-category-view', @@ -1725,11 +1759,20 @@ ), 'scripts' => array(), ), - 'tablet.scripts' => $wgMFResourceFileModuleBoilerplate + array( + 'skins.minerva.tablet.scripts' => $wgMFResourceFileModuleBoilerplate + array( 'dependencies' => array( // Feature modules that should be loaded on tablets should be listed below here. 'mobile.toc', ), + 'scripts' => array( + 'resources/skins.minerva.tablet.scripts/toc.js', + ), + ), + // Remove when cache clears + 'tablet.scripts' => array( + 'dependencies' => array( + 'skins.minerva.tablet.scripts', + ), ), ); diff --git a/includes/skins/SkinMinerva.php b/includes/skins/SkinMinerva.php index 97d9230..dc3ca0e 100644 --- a/includes/skins/SkinMinerva.php +++ b/includes/skins/SkinMinerva.php @@ -1015,12 +1015,12 @@ if ( $user->isLoggedIn() ) { if ( $this->useEcho() ) { - $modules[] = 'mobile.notifications'; + $modules[] = 'skins.minerva.notifications'; } if ( $this->isCurrentPageEditable() ) { if ( $action === 'signup-edit' || $campaign === 'leftNavSignup' ) { - $modules[] = 'mobile.newusers'; + $modules[] = 'skins.minerva.newusers'; } } } @@ -1030,7 +1030,7 @@ ( $this->isTalkAllowed() || $title->isTalkPage() ) && $this->isWikiTextTalkPage() ) { - $modules[] = 'mobile.talk'; + $modules[] = 'skins.minerva.talk'; } return $modules; @@ -1048,7 +1048,7 @@ $modules['legacy'] = array(); // Add minerva specific modules - $modules['head'] = 'mobile.head'; + $modules['head'] = 'skins.minerva.scripts.top'; // Define all the modules that should load on the mobile site and their dependencies. // Do not add mobules here. $modules['stable'] = 'skins.minerva.scripts'; @@ -1057,23 +1057,22 @@ $modules['watch'] = array(); if ( $this->isAllowedPageAction( 'watch' ) ) { // Explicitly add the mobile watchstar code. - $modules['watch'] = array( 'mobile.watchstar.init' ); + $modules['watch'] = array( 'skins.minerva.watchstar' ); } if ( $this->isAllowedPageAction( 'edit' ) ) { - $modules['editor'] = array( 'mobile.editor' ); + $modules['editor'] = array( 'skins.minerva.editor' ); } // add the browse module if the page has a tag assigned to it if ( $this->getBrowseTags( $this->getTitle() ) ) { - $modules['browse'] = array( 'mobile.browse' ); + $modules['browse'] = array( 'skins.minerva.browse' ); } $modules['context'] = $this->getContextSpecificModules(); if ( $this->isMobileMode ) { - $modules['toggling'] = array( 'mobile.toggling' ); - $modules['eventlogging'] = array( 'mobile.loggingSchemas' ); + $modules['toggling'] = array( 'skins.minerva.toggling' ); } $modules['site'] = 'mobile.site'; diff --git a/includes/skins/SkinMinervaBeta.php b/includes/skins/SkinMinervaBeta.php index befdbb9..3e3ce77 100644 --- a/includes/skins/SkinMinervaBeta.php +++ b/includes/skins/SkinMinervaBeta.php @@ -66,7 +66,7 @@ public function getContextSpecificModules() { $modules = parent::getContextSpecificModules(); if ( $this->getCategoryLinks( false ) ) { - $modules[] = 'mobile.categories'; + $modules[] = 'skins.minerva.categories'; } return $modules; diff --git a/resources/mobile.editor.common/EditorOverlayBase.js b/resources/mobile.editor.common/EditorOverlayBase.js index 850a570..33dea14 100644 --- a/resources/mobile.editor.common/EditorOverlayBase.js +++ b/resources/mobile.editor.common/EditorOverlayBase.js @@ -5,7 +5,6 @@ Icon = M.require( 'Icon' ), toast = M.require( 'toast' ), user = M.require( 'user' ), - pageApi = M.require( 'pageApi' ), EditorOverlayBase; /** @@ -43,6 +42,7 @@ /** * @inheritdoc * @cfg {Object} defaults Default options hash. + * @cfg {PageApi} defaults.pageApi an api module to retrieve pages. * @cfg {Boolean} defaults.hasToolbar Whether the editor has a toolbar or not. When * disabled a header will be show instead. * @cfg {String} defaults.continueMsg Caption for the next button on edit form which takes @@ -67,6 +67,7 @@ * released to inform the user. */ defaults: $.extend( {}, Overlay.prototype.defaults, { + pageApi: undefined, hasToolbar: false, continueMsg: mw.msg( 'mobile-frontend-editor-continue' ), cancelMsg: mw.msg( 'mobile-frontend-editor-cancel' ), @@ -145,7 +146,7 @@ self = this; // FIXME: use generic method for following 3 lines - pageApi.invalidatePage( title ); + this.options.pageApi.invalidatePage( title ); if ( this.isNewPage ) { msg = 'mobile-frontend-editor-success-new-page'; diff --git a/resources/mobile.issues/init.js b/resources/mobile.issues/cleanuptemplates.js similarity index 94% rename from resources/mobile.issues/init.js rename to resources/mobile.issues/cleanuptemplates.js index 3e53ad1..58d0cde 100644 --- a/resources/mobile.issues/init.js +++ b/resources/mobile.issues/cleanuptemplates.js @@ -114,14 +114,8 @@ } } - // Setup the issues banner on the page - initPageIssues(); - // Show it in edit preview. - M.on( 'edit-preview', function ( overlay ) { - initPageIssues( overlay.$el ); - } ); - return { + init: initPageIssues, createBanner: createBanner, _extractMessage: extractMessage }; diff --git a/resources/mobile.references/init.js b/resources/mobile.references/references.js similarity index 97% rename from resources/mobile.references/init.js rename to resources/mobile.references/references.js index a800fcc..7354e8c 100644 --- a/resources/mobile.references/init.js +++ b/resources/mobile.references/references.js @@ -62,10 +62,6 @@ } - $( function () { - setup(); - } ); - M.define( 'references', { setup: setup } ); diff --git a/resources/mobile.startup/Skin.js b/resources/mobile.startup/Skin.js index 24ae215..a352a2c 100644 --- a/resources/mobile.startup/Skin.js +++ b/resources/mobile.startup/Skin.js @@ -102,9 +102,10 @@ this.page = options.page; this.name = options.name; - this.tabletModules = options.tabletModules; this.mainMenu = options.mainMenu; View.prototype.initialize.apply( this, arguments ); + // Must be run after merging with defaults as must be defined. + this.tabletModules = options.tabletModules; /** * Tests current window size and if suitable loads styles and scripts specific for larger devices diff --git a/resources/mobile.talk.overlays/TalkOverlay.js b/resources/mobile.talk.overlays/TalkOverlay.js index e80d28d..c0a48a4 100644 --- a/resources/mobile.talk.overlays/TalkOverlay.js +++ b/resources/mobile.talk.overlays/TalkOverlay.js @@ -3,7 +3,6 @@ Overlay = M.require( 'Overlay' ), Page = M.require( 'Page' ), Anchor = M.require( 'Anchor' ), - pageApi = M.require( 'pageApi' ), user = M.require( 'user' ), /** * Overlay for talk page @@ -20,6 +19,7 @@ /** * @inheritdoc * @cfg {Object} defaults Default options hash. + * @cfg {PageApi} defaults.pageApi an api module to retrieve pages. * @cfg {Array} defaults.headings A list of {Section} objects to render heading links * for. If not set ajax request will be performed. * @cfg {String} defaults.heading Heading for talk overlay. @@ -95,7 +95,7 @@ this.$( '.topic-title-list' ).empty(); // FIXME: use Page's mechanisms for retrieving page data instead - pageApi.getPage( options.title ).fail( function ( resp ) { + this.options.pageApi.getPage( options.title ).fail( function ( resp ) { // If the API returns the error code 'missingtitle', that means the // talk page doesn't exist yet. if ( resp === 'missingtitle' ) { diff --git a/resources/mobile.talk.overlays/TalkSectionAddOverlay.js b/resources/mobile.talk.overlays/TalkSectionAddOverlay.js index 6cec9aa..20465fa 100644 --- a/resources/mobile.talk.overlays/TalkSectionAddOverlay.js +++ b/resources/mobile.talk.overlays/TalkSectionAddOverlay.js @@ -2,7 +2,6 @@ var Overlay = M.require( 'Overlay' ), api = M.require( 'api' ), - pageApi = M.require( 'pageApi' ), toast = M.require( 'toast' ), Icon = M.require( 'Icon' ), TalkSectionAddOverlay; @@ -18,6 +17,7 @@ /** * @inheritdoc * @cfg {Object} defaults Default options hash. + * @cfg {PageApi} defaults.pageApi an api module to retrieve pages. * @cfg {String} defaults.cancelMsg Caption for cancel button on edit form. * @cfg {String} defaults.topicTitlePlaceHolder Placeholder text to prompt user to add * a talk page topic subject. @@ -101,7 +101,7 @@ if ( status === 'ok' ) { // Check if the user was previously on the talk overlay if ( self.title !== mw.config.get( 'wgPageName' ) ) { - pageApi.invalidatePage( self.title ); + self.options.pageApi.invalidatePage( self.title ); toast.show( mw.msg( 'mobile-frontend-talk-topic-feedback' ), 'toast' ); M.emit( 'talk-discussion-added' ); window.history.back(); diff --git a/resources/mobile.talk.overlays/TalkSectionOverlay.js b/resources/mobile.talk.overlays/TalkSectionOverlay.js index 9fc364e..ae4a16c 100644 --- a/resources/mobile.talk.overlays/TalkSectionOverlay.js +++ b/resources/mobile.talk.overlays/TalkSectionOverlay.js @@ -6,7 +6,6 @@ user = M.require( 'user' ), Page = M.require( 'Page' ), Button = M.require( 'Button' ), - pageApi = M.require( 'pageApi' ), TalkSectionOverlay; /** @@ -26,6 +25,7 @@ /** * @inheritdoc * @cfg {Object} defaults Default options hash. + * @cfg {PageApi} defaults.pageApi an api module to retrieve pages. * @cfg {String} defaults.title Title. * @cfg {Section} defaults.section that is currently being viewed in overlay. * @cfg {String} defaults.reply Reply heading. @@ -33,6 +33,7 @@ * automatically signed. */ defaults: $.extend( {}, Overlay.prototype.defaults, { + pageApi: undefined, saveButton: new Button( { block: true, additionalClassNames: 'save-button', @@ -83,7 +84,7 @@ renderFromApi: function ( options ) { var self = this; - pageApi.getPage( options.title ).done( function ( pageData ) { + this.options.pageApi.getPage( options.title ).done( function ( pageData ) { var page = new Page( pageData ); options.section = page.getSection( options.id ); self.render( options ); @@ -117,7 +118,7 @@ } ).done( function () { popup.show( mw.msg( 'mobile-frontend-talk-reply-success' ), 'toast' ); // invalidate the cache - pageApi.invalidatePage( self.options.title ); + self.options.pageApi.invalidatePage( self.options.title ); self.renderFromApi( self.options ); } ).fail( function ( data, response ) { diff --git a/resources/mobile.toggling/init.js b/resources/mobile.toggle/toggle.js similarity index 80% rename from resources/mobile.toggling/init.js rename to resources/mobile.toggle/toggle.js index bcecb12..9aba91b 100644 --- a/resources/mobile.toggling/init.js +++ b/resources/mobile.toggle/toggle.js @@ -1,9 +1,5 @@ ( function ( M, $ ) { - var page = M.getCurrentPage(), - currentPageTitle = page.title, - // FIXME: Clean up when cache clears. - $contentContainer = $( '#content #bodyContent, #content_wrapper #content' ), - context = M.require( 'context' ), + var context = M.require( 'context' ), settings = M.require( 'settings' ), browser = M.require( 'browser' ), escapeHash = M.require( 'util' ).escapeHash, @@ -22,14 +18,15 @@ * existing page. * * @method + * @param {Page} page * @returns {Object} representing open sections * @ignore */ - function getExpandedSections() { + function getExpandedSections( page ) { var expandedSections = $.parseJSON( settings.get( 'expandedSections', false ) || '{}' ); - expandedSections[currentPageTitle] = expandedSections[currentPageTitle] || {}; + expandedSections[page.title] = expandedSections[page.title] || {}; return expandedSections; } @@ -49,18 +46,19 @@ * If the heading is collapsed, remove it from localStorage. * * @param {jQuery.Object} $heading - A heading belonging to a section + * @param {Page} page * @ignore */ - function storeSectionToggleState( $heading ) { + function storeSectionToggleState( $heading, page ) { var headline = $heading.find( 'span' ).attr( 'id' ), isSectionOpen = $heading.hasClass( 'open-block' ), - expandedSections = getExpandedSections(); + expandedSections = getExpandedSections( page ); if ( headline ) { if ( isSectionOpen ) { - expandedSections[currentPageTitle][headline] = ( new Date() ).getTime(); + expandedSections[page.title][headline] = ( new Date() ).getTime(); } else { - delete expandedSections[currentPageTitle][headline]; + delete expandedSections[page.title][headline]; } saveExpandedSections( expandedSections ); @@ -70,11 +68,12 @@ /** * Expand sections that were previously expanded before leaving this page. * @param {jQuery.Object} $container + * @param {Page} page * @ignore */ - function expandStoredSections( $container ) { + function expandStoredSections( $container, page ) { var $sectionHeading, $headline, - expandedSections = getExpandedSections(), + expandedSections = getExpandedSections( page ), $headlines = $container.find( '.section-heading span' ); $headlines.each( function () { @@ -82,10 +81,10 @@ $sectionHeading = $headline.parents( '.section-heading' ); // toggle only if the section is not already expanded if ( - expandedSections[currentPageTitle][$headline.attr( 'id' )] && + expandedSections[page.title][$headline.attr( 'id' )] && !$sectionHeading.hasClass( 'open-block' ) ) { - toggle( $sectionHeading ); + toggle( $sectionHeading, page ); } } ); } @@ -93,11 +92,12 @@ /** * Clean obsolete (saved more than a day ago) expanded sections from * localStorage. + * @param {Page} page * @ignore */ - function cleanObsoleteStoredSections() { + function cleanObsoleteStoredSections( page ) { var now = ( new Date() ).getTime(), - expandedSections = getExpandedSections(), + expandedSections = getExpandedSections( page ), // the number of days between now and the time a setting was saved daysDifference; $.each( expandedSections, function ( page, sections ) { @@ -120,6 +120,7 @@ */ function toggle( $heading ) { var isCollapsed = $heading.is( '.open-block' ), + page = $heading.data( 'page' ), options, indicator; $heading.toggleClass( 'open-block' ); @@ -137,7 +138,7 @@ } ); if ( !browser.isWideScreen() ) { - storeSectionToggleState( $heading ); + storeSectionToggleState( $heading, page ); } } @@ -195,11 +196,10 @@ * @param {String} prefix a prefix to use for the id. * @ignore */ - function enable( $container, prefix ) { + function enable( $container, prefix, page ) { var tagName, expandSections, indicator, $firstHeading, collapseSectionsByDefault = mw.config.get( 'wgMFCollapseSectionsByDefault' ); - $container = $container || $contentContainer; // Also allow .section-heading if some extensions like Wikibase // want to toggle other headlines than direct descendants of $container. @@ -221,6 +221,7 @@ if ( $heading.next().is( 'div' ) ) { $heading .addClass( 'collapsible-heading ' ) + .data( 'page', page ) .attr( { tabindex: 0, 'aria-haspopup': 'true', @@ -287,7 +288,7 @@ checkInternalRedirectAndHash(); checkHash(); // Restricted to links created by editors and thus outside our control - $contentContainer.find( 'a' ).on( 'click', function () { + $container.find( 'a' ).on( 'click', function () { // the link might be an internal link with a hash. // if it is check if we need to reveal any sections. if ( $( this ).attr( 'href' ) !== undefined && @@ -298,47 +299,15 @@ } ); if ( !browser.isWideScreen() ) { - expandStoredSections( $container ); - cleanObsoleteStoredSections(); + expandStoredSections( $container, page ); + cleanObsoleteStoredSections( page ); } - } - - /** - * Initialises toggling code. - * - * @method - * @param {jQuery.Object} $container to enable toggling on - * @param {String} prefix a prefix to use for the id. - * @ignore - */ - function init( $container, prefix ) { - // distinguish headings in content from other headings - $container.find( '> h1,> h2,> h3,> h4,> h5,> h6' ).addClass( 'section-heading' ); - enable( $container, prefix ); - - // FIXME: remove when cache clears - $( function () { - $container.find( '.open-block > a.edit-page, .in-block > a.edit-page' ).each( function ( i, el ) { - $( el ).wrap( '<span></span>' ); - } ); - } ); - } - - // avoid this running on Watchlist - if ( - !page.inNamespace( 'special' ) && - !mw.config.get( 'wgIsMainPage' ) && - mw.config.get( 'wgAction' ) === 'view' - ) { - init( $contentContainer, 'content-' ); } M.define( 'toggle', { reveal: reveal, toggle: toggle, enable: enable, - // for tests - _currentPageTitle: currentPageTitle, _getExpandedSections: getExpandedSections, _expandStoredSections: expandStoredSections, _cleanObsoleteStoredSections: cleanObsoleteStoredSections diff --git a/resources/mobile.toggling/toggle.less b/resources/mobile.toggle/toggle.less similarity index 100% rename from resources/mobile.toggling/toggle.less rename to resources/mobile.toggle/toggle.less diff --git a/resources/skins.minerva.alpha.scripts/quickLookup.js b/resources/skins.minerva.alpha.scripts/quickLookup.js new file mode 100644 index 0000000..74007c6 --- /dev/null +++ b/resources/skins.minerva.alpha.scripts/quickLookup.js @@ -0,0 +1,114 @@ +( function ( M, $ ) { + var api = M.require( 'api' ), + toast = M.require( 'toast' ), + Swipe = M.require( 'Swipe' ), + swipe, + QuickLookupDrawer = M.require( 'modules/quickLookup/QuickLookupDrawer' ), + hostname = window.location.hostname, + cache = {}, + drawer; + + M.require( 'context' ).assertMode( [ 'alpha' ] ); + /** + * Search API for a brief intro about a page. + * @ignore + * @param {String} title title of the page + */ + function lookup( title ) { + var deferred = $.Deferred(), + promise = deferred.promise(); + + if ( cache.hasOwnProperty( title ) ) { + if ( cache[title] ) { + deferred.resolve( cache[title] ); + } else { + deferred.reject(); + } + } else { + api.get( { + prop: 'extracts', + exsentences: 5, + titles: title, + exintro: '', + continue: '', + explaintext: '' + } ).then( function ( data ) { + var pages = OO.getProp( data, 'query', 'pages' ), + pageID, + extract; + + cache[title] = null; // just to mark that we searched the API + if ( pages ) { + for ( pageID in pages ) { + if ( pages.hasOwnProperty( pageID ) ) { + extract = OO.getProp( pages, pageID, 'extract' ); + if ( extract ) { + cache[title] = { + title: title, + text: extract, + id: pageID + }; + deferred.resolve( cache[title] ); + break; + } + } + } + } + if ( cache[title] === null ) { + deferred.reject(); + } + } ).fail( deferred.reject ); + } + + return promise; + } + + /** + * Show a QuickLookupDrawer with information about {link} + * Link must have the same hostname as the site, i.e. it must be an internal link. + * Show a toast before searching and a drawer with page info after the search is successful. + * @ignore + * @param {jQuery.Event} ev Event object of the swipe gesture + */ + function showDrawer( ev ) { + var link = ev.currentTarget, + linkTitle = link.title, + linkHostname = link.hostname; + + toast.hide(); + if ( drawer ) { + drawer.hide(); + } + + if ( linkHostname === hostname && linkTitle ) { + toast.show( mw.msg( 'mobile-frontend-quick-lookup-looking', linkTitle ), 'toast quick-lookup' ); + lookup( linkTitle ).done( function ( page ) { + toast.hide(); + drawer = new QuickLookupDrawer( page ); + drawer.show(); + } ).fail( function () { + toast.show( + mw.msg( 'mobile-frontend-quick-lookup-no-results', linkTitle ), + 'toast quick-lookup' + ); + } ); + } else { + // @todo Remove the sitename parameter late 2015 as it only exists for B/C. + toast.show( + mw.msg( 'mobile-frontend-quick-lookup-not-internal', mw.config.get( 'wgSiteName' ) ), + 'toast quick-lookup' + ); + } + } + + $( function () { + // initialize swipe module + swipe = new Swipe(); + // listen on our wanted swipe directions + swipe + .on( 'swipe-right', $.proxy( showDrawer ) ) + .on( 'swipe-left', $.proxy( showDrawer ) ); + // listen on all links + swipe.setElement( $( 'a' ) ); + } ); +}( mw.mobileFrontend, jQuery ) ); diff --git a/resources/mobile.fontchanger.init/init.js b/resources/skins.minerva.beta.scripts/fontchanger.js similarity index 100% rename from resources/mobile.fontchanger.init/init.js rename to resources/skins.minerva.beta.scripts/fontchanger.js diff --git a/resources/mobile.categories/init.js b/resources/skins.minerva.categories/init.js similarity index 100% rename from resources/mobile.categories/init.js rename to resources/skins.minerva.categories/init.js diff --git a/resources/mobile.editor/init.js b/resources/skins.minerva.editor/init.js similarity index 99% rename from resources/mobile.editor/init.js rename to resources/skins.minerva.editor/init.js index 403d10c..b068434 100644 --- a/resources/mobile.editor/init.js +++ b/resources/skins.minerva.editor/init.js @@ -17,6 +17,7 @@ name: 'edit-enabled' } ), currentPage = M.getCurrentPage(), + pageApi = M.require( 'pageApi' ), enabledClass = enabledEditIcon.getGlyphClassName(), disabledClass = disabledEditIcon.getGlyphClassName(), context = M.require( 'context' ), @@ -130,6 +131,7 @@ result = $.Deferred(), preferredEditor = getPreferredEditor(), editorOptions = { + pageApi: pageApi, licenseMsg: skin.getLicenseMsg(), title: page.title, isAnon: user.isAnon(), diff --git a/resources/mobile.newusers/init.js b/resources/skins.minerva.newusers/init.js similarity index 100% rename from resources/mobile.newusers/init.js rename to resources/skins.minerva.newusers/init.js diff --git a/resources/mobile.notifications/init.js b/resources/skins.minerva.notifications/init.js similarity index 100% rename from resources/mobile.notifications/init.js rename to resources/skins.minerva.notifications/init.js diff --git a/resources/mobile.head/init.js b/resources/skins.minerva.scripts.top/init.js similarity index 100% rename from resources/mobile.head/init.js rename to resources/skins.minerva.scripts.top/init.js diff --git a/resources/skins.minerva.scripts/init.js b/resources/skins.minerva.scripts/init.js index 847c5b8..b5c97d4 100644 --- a/resources/skins.minerva.scripts/init.js +++ b/resources/skins.minerva.scripts/init.js @@ -6,6 +6,8 @@ loader = M.require( 'loader' ), router = M.require( 'router' ), context = M.require( 'context' ), + references = M.require( 'references' ), + cleanuptemplates = M.require( 'cleanuptemplates' ), useNewMediaViewer = context.isBetaGroupMember(), overlayManager = M.require( 'overlayManager' ), page = M.getCurrentPage(), @@ -103,8 +105,11 @@ M.on( 'photo-loaded', initMediaViewer ); // Setup - $( initButton ); - initMediaViewer(); + $( function () { + initButton(); + initMediaViewer(); + references.setup(); + } ); // local storage is supported in this case, when ~ means it was dismissed if ( token !== false && token !== '~' && !page.isMainPage() && !page.inNamespace( 'special' ) ) { @@ -130,6 +135,13 @@ } } + // Setup the issues banner on the page + cleanuptemplates.init(); + // Show it in edit preview. + M.on( 'edit-preview', function ( overlay ) { + cleanuptemplates.init( overlay.$el ); + } ); + // let the interested parties know whether the panel is shown mw.track( 'minerva.betaoptin', { isPanelShown: betaOptinPanel !== undefined diff --git a/resources/mobile.redirect/init.js b/resources/skins.minerva.scripts/mobileRedirect.js similarity index 100% rename from resources/mobile.redirect/init.js rename to resources/skins.minerva.scripts/mobileRedirect.js diff --git a/resources/mobile.startup/init.js b/resources/skins.minerva.scripts/preInit.js similarity index 96% rename from resources/mobile.startup/init.js rename to resources/skins.minerva.scripts/preInit.js index 7eaa259..cee8e76 100644 --- a/resources/mobile.startup/init.js +++ b/resources/skins.minerva.scripts/preInit.js @@ -17,7 +17,7 @@ skin = new Skin( { el: 'body', - tabletModules: mw.config.get( 'skin' ) === 'minerva' ? [ 'tablet.scripts' ] : [], + tabletModules: mw.config.get( 'skin' ) === 'minerva' ? [ 'skins.minerva.tablet.scripts' ] : [], page: getCurrentPage(), mainMenu: mainMenu } ); diff --git a/resources/mobile.search/init.js b/resources/skins.minerva.scripts/search.js similarity index 100% rename from resources/mobile.search/init.js rename to resources/skins.minerva.scripts/search.js diff --git a/resources/mobile.toc/init.js b/resources/skins.minerva.tablet.scripts/toc.js similarity index 100% rename from resources/mobile.toc/init.js rename to resources/skins.minerva.tablet.scripts/toc.js diff --git a/resources/mobile.talk/init.js b/resources/skins.minerva.talk/init.js similarity index 97% rename from resources/mobile.talk/init.js rename to resources/skins.minerva.talk/init.js index 46fd661..3934623 100644 --- a/resources/mobile.talk/init.js +++ b/resources/skins.minerva.talk/init.js @@ -1,5 +1,6 @@ ( function ( M, $ ) { var loader = M.require( 'loader' ), + pageApi = M.require( 'pageApi' ), LoadingOverlay = M.require( 'LoadingOverlay' ), user = M.require( 'user' ), Button = M.require( 'Button' ), @@ -12,6 +13,7 @@ overlayManager.add( /^\/talk\/?(.*)$/, function ( id ) { var result = $.Deferred(), talkOptions = { + pageApi: pageApi, title: title, licenseMsg: skin.getLicenseMsg() }; diff --git a/resources/mobile.talk/talk.less b/resources/skins.minerva.talk/talk.less similarity index 100% rename from resources/mobile.talk/talk.less rename to resources/skins.minerva.talk/talk.less diff --git a/resources/skins.minerva.toggling/init.js b/resources/skins.minerva.toggling/init.js new file mode 100644 index 0000000..97ee383 --- /dev/null +++ b/resources/skins.minerva.toggling/init.js @@ -0,0 +1,29 @@ +( function ( M, $ ) { + var page = M.getCurrentPage(), + // FIXME: Clean up when cache clears. + $contentContainer = $( '#content #bodyContent, #content_wrapper #content' ), + toggle = M.require( 'toggle' ); + + /** + * Initialises toggling code. + * + * @method + * @param {jQuery.Object} $container to enable toggling on + * @param {String} prefix a prefix to use for the id. + * @ignore + */ + function init( $container, prefix ) { + // distinguish headings in content from other headings + $container.find( '> h1,> h2,> h3,> h4,> h5,> h6' ).addClass( 'section-heading' ); + toggle.enable( $container, prefix ); + } + + // avoid this running on Watchlist + if ( + !page.inNamespace( 'special' ) && + !mw.config.get( 'wgIsMainPage' ) && + mw.config.get( 'wgAction' ) === 'view' + ) { + init( $contentContainer, 'content-' ); + } +}( mw.mobileFrontend, jQuery ) ); diff --git a/resources/mobile.watchstar.init/init.js b/resources/skins.minerva.watchstar/init.js similarity index 100% rename from resources/mobile.watchstar.init/init.js rename to resources/skins.minerva.watchstar/init.js diff --git a/tests/browser/features/step_definitions/notification_steps.rb b/tests/browser/features/step_definitions/notification_steps.rb index e2e5e35..d73cec0 100644 --- a/tests/browser/features/step_definitions/notification_steps.rb +++ b/tests/browser/features/step_definitions/notification_steps.rb @@ -5,7 +5,7 @@ # TODO: If this approach works well, we should implement general # `wait_for_resource` and `resource_ready?` helper methods in # mw-selenium, and document this pattern on mw.org - browser.execute_script("return mw.loader.getState('mobile.notifications') === 'ready'") + browser.execute_script("return mw.loader.getState('skins.minerva.notifications') === 'ready'") end page.notifications_button_element.when_present.click diff --git a/tests/qunit/mobile.issues/test_init.js b/tests/qunit/mobile.issues/test_cleanuptemplates.js similarity index 100% rename from tests/qunit/mobile.issues/test_init.js rename to tests/qunit/mobile.issues/test_cleanuptemplates.js diff --git a/tests/qunit/mobile.references/test_init.js b/tests/qunit/mobile.references/test_references.js similarity index 100% rename from tests/qunit/mobile.references/test_init.js rename to tests/qunit/mobile.references/test_references.js diff --git a/tests/qunit/mobile.talk.overlays/test_TalkOverlay.js b/tests/qunit/mobile.talk.overlays/test_TalkOverlay.js index 10ea097..cdb3df4 100644 --- a/tests/qunit/mobile.talk.overlays/test_TalkOverlay.js +++ b/tests/qunit/mobile.talk.overlays/test_TalkOverlay.js @@ -1,6 +1,7 @@ ( function ( M, $ ) { - var pageApi = M.require( 'pageApi' ), + var PageApi = M.require( 'PageApi' ), + pageApi = new PageApi(), TalkOverlay = M.require( 'modules/talk/TalkOverlay' ); QUnit.module( 'MobileFrontend TalkOverlay', { @@ -30,6 +31,7 @@ QUnit.test( '#TalkOverlay (new page; anonymous)', 4, function ( assert ) { var options = { + pageApi: pageApi, title: 'Talk:No exist' }, overlay = new TalkOverlay( options ), @@ -52,6 +54,7 @@ mw.config.set( 'wgUserName', 'FlorianSW' ); overlay = new TalkOverlay( { + pageApi: pageApi, title: 'Talk:No exist' } ); @@ -63,6 +66,7 @@ QUnit.test( '#TalkOverlay (existing page lists section headings)', 4, function ( assert ) { var overlay = new TalkOverlay( { + pageApi: pageApi, title: 'Talk:Topic' } ); diff --git a/tests/qunit/mobile.talk.overlays/test_TalkSectionOverlay.js b/tests/qunit/mobile.talk.overlays/test_TalkSectionOverlay.js index dd55b08..2c7c6d3 100644 --- a/tests/qunit/mobile.talk.overlays/test_TalkSectionOverlay.js +++ b/tests/qunit/mobile.talk.overlays/test_TalkSectionOverlay.js @@ -2,6 +2,8 @@ var TalkSectionOverlay = M.require( 'modules/talk/TalkSectionOverlay' ), api = M.require( 'api' ), + PageApi = M.require( 'PageApi' ), + pageApi = new PageApi(), user = M.require( 'user' ), renderFromApiSpy; @@ -48,6 +50,7 @@ QUnit.test( 'Check api request on save', 1, function ( assert ) { var spy = this.sandbox.stub( api, 'postWithToken' ).returns( $.Deferred().resolve() ), overlay = new TalkSectionOverlay( { + pageApi: pageApi, title: 'Talk:Test', id: 1, section: 'Test' diff --git a/tests/qunit/mobile.toggling/test_init.js b/tests/qunit/mobile.toggle/test_toggle.js similarity index 90% rename from tests/qunit/mobile.toggling/test_init.js rename to tests/qunit/mobile.toggle/test_toggle.js index 4a12ad7..8077eeb 100644 --- a/tests/qunit/mobile.toggling/test_init.js +++ b/tests/qunit/mobile.toggle/test_toggle.js @@ -3,6 +3,7 @@ var sectionHtml = mw.template.get( 'tests.mobile.templates', 'section.hogan' ).render(), settings = M.require( 'settings' ), browser = M.require( 'browser' ), + page = { title: 'Toggle test' }, toggle = M.require( 'toggle' ); /** @@ -16,7 +17,7 @@ this.$container = $( '<div>' ).html( sectionHtml ); this.$section0 = this.$container.find( 'h2' ).eq( 0 ); this.sandbox.stub( browser, 'isWideScreen' ).returns( false ); - toggle.enable( this.$container ); + toggle.enable( this.$container, '', page ); toggle.toggle( this.$section0 ); }, teardown: function () { @@ -99,7 +100,7 @@ setup: function () { this.$container = $( '<div>' ).html( sectionHtml ); this.sandbox.stub( browser, 'isWideScreen' ).returns( true ); - toggle.enable( this.$container ); + toggle.enable( this.$container, '', page ); }, teardown: function () { window.location.hash = '#'; @@ -123,7 +124,7 @@ this.sandbox.stub( mw.config, 'get' ).withArgs( 'wgMFCollapseSectionsByDefault' ).returns( false ); settings.save( 'expandSections', 'true', true ); this.$container = $( '<div>' ).html( sectionHtml ); - toggle.enable( this.$container ); + toggle.enable( this.$container, '', page ); }, teardown: function () { window.location.hash = '#'; @@ -147,7 +148,7 @@ this.sandbox.stub( mw.config, 'get' ).withArgs( 'wgMFCollapseSectionsByDefault' ).returns( true ); this.$container = $( '<div>' ).html( sectionHtml ); this.sandbox.stub( browser, 'isWideScreen' ).returns( false ); - toggle.enable( this.$container ); + toggle.enable( this.$container, '', page ); }, teardown: function () { window.location.hash = '#'; @@ -189,11 +190,11 @@ this.sandbox.stub( mw.config, 'get' ).withArgs( 'wgMFCollapseSectionsByDefault' ).returns( true ); this.sandbox.stub( browser, 'isWideScreen' ).returns( false ); this.$container = $( '<div>' ).html( sectionHtml ); - toggle.enable( this.$container ); + toggle.enable( this.$container, '', page ); this.$section = this.$container.find( 'h2' ); this.headline = this.$section.find( 'span' ).attr( 'id' ); - this.pageTitle = toggle._currentPageTitle; - this.expandedSections = toggle._getExpandedSections( this.pageTitle ); + this.pageTitle = page.title; + this.expandedSections = toggle._getExpandedSections( page ); }, teardown: function () { window.location.hash = '#'; @@ -209,14 +210,14 @@ ); toggle.toggle( this.$section ); - this.expandedSections = toggle._getExpandedSections( this.pageTitle ); + this.expandedSections = toggle._getExpandedSections( page ); assert.strictEqual( typeof this.expandedSections[ this.pageTitle ][ this.headline ], 'number', 'the just toggled section state has been saved' ); toggle.toggle( this.$section ); - this.expandedSections = toggle._getExpandedSections( this.pageTitle ); + this.expandedSections = toggle._getExpandedSections( page ); assert.strictEqual( this.expandedSections[ this.pageTitle ][ this.headline ], undefined, 'the just toggled section state has been removed' @@ -228,14 +229,14 @@ settings.save( 'expandedSections', JSON.stringify( this.expandedSections ) ); - this.expandedSections = toggle._getExpandedSections( this.pageTitle ); + this.expandedSections = toggle._getExpandedSections( page ); assert.strictEqual( typeof this.expandedSections[ this.pageTitle ][ this.headline ], 'number', 'manually created section state has been saved correctly' ); - toggle._cleanObsoleteStoredSections(); - this.expandedSections = toggle._getExpandedSections( this.pageTitle ); + toggle._cleanObsoleteStoredSections( page ); + this.expandedSections = toggle._getExpandedSections( page ); assert.strictEqual( this.expandedSections[ this.pageTitle ][ this.headline ], undefined, 'section, whose store time is manually changed to an older date,' + @@ -244,7 +245,7 @@ } ); QUnit.test( 'Expanding already expanded section does not toggle it.', 5, function ( assert ) { - this.expandedSections = toggle._getExpandedSections( this.pageTitle ); + this.expandedSections = toggle._getExpandedSections( page ); assert.strictEqual( $.isEmptyObject( this.expandedSections[ this.pageTitle ] ), true, 'no expanded sections are stored in localStorage yet' @@ -265,13 +266,13 @@ 'revealed section has open-block class' ); - this.expandedSections = toggle._getExpandedSections( this.pageTitle ); + this.expandedSections = toggle._getExpandedSections( page ); assert.strictEqual( typeof this.expandedSections[ this.pageTitle ][ this.headline ], 'number', 'manually revealed section state has been correctly saved in localStorage' ); - toggle._expandStoredSections( this.$container ); + toggle._expandStoredSections( this.$container, page ); assert.strictEqual( this.$section.hasClass( 'open-block' ), @@ -289,8 +290,8 @@ this.$container.find( 'h2' ).addClass( 'section-heading' ); this.$section = this.$container.find( 'h2' ).eq( 0 ); this.headline = 'First_Section'; - this.pageTitle = toggle._currentPageTitle; - this.expandedSections = toggle._getExpandedSections( this.pageTitle ); + this.pageTitle = page.title; + this.expandedSections = toggle._getExpandedSections( page ); }, teardown: function () { window.location.hash = '#'; @@ -310,15 +311,15 @@ // save a toggle state manually this.expandedSections[ this.pageTitle ][ this.headline ] = ( new Date() ).getTime(); settings.save( 'expandedSections', JSON.stringify( this.expandedSections ), false ); - this.expandedSections = toggle._getExpandedSections( this.pageTitle ); + this.expandedSections = toggle._getExpandedSections( page ); assert.strictEqual( typeof this.expandedSections[ this.pageTitle ][ this.headline ], 'number', 'manually created section state has been saved correctly' ); - toggle.enable( this.$container ); + toggle.enable( this.$container, '', page ); - this.expandedSections = toggle._getExpandedSections( this.pageTitle ); + this.expandedSections = toggle._getExpandedSections( page ); assert.strictEqual( typeof this.expandedSections[ this.pageTitle ][ this.headline ], 'number', 'manually created section state is still active after toggle.init()' diff --git a/tests/qunit/mobile.watchstar/test_Watchstar.js b/tests/qunit/mobile.watchstar/test_Watchstar.js index c4c2389..a2fe4e8 100644 --- a/tests/qunit/mobile.watchstar/test_Watchstar.js +++ b/tests/qunit/mobile.watchstar/test_Watchstar.js @@ -30,7 +30,8 @@ } ); $el.trigger( 'click' ); - // Note due to the fact isVisible uses a timeout we cannot easily test this + // position-fixed class may not have loaded and without it the toast is not visible so use + // a spy rather than directly testing toast element visibility assert.ok( this.spy.called, 'We checked if the drawer was visible before displaying it' ); } ); @@ -42,6 +43,7 @@ // FIXME: Should Schema.log be stubbed by default? this.stub( SchemaMobileWebWatching.prototype, 'log' ).returns( null ); + this.toastSpy = this.sandbox.spy( toast, 'show' ); }, teardown: function () { // Hide any existing toasts @@ -66,7 +68,7 @@ } ), 'The watch happened' ); assert.strictEqual( $el.hasClass( watchIcon.getGlyphClassName() ), true, 'After successful watch has watched class' ); - assert.strictEqual( $( '.toast' ).is( ':visible' ), true, 'A toast is shown' ); + assert.ok( this.toastSpy.calledOnce, 'A toast is shown' ); } ); QUnit.test( 'Logged in user unwatches article', 2, function ( assert ) { @@ -85,7 +87,7 @@ unwatch: true, pageids: 42 } ), 'The watch happened' ); - assert.strictEqual( $( '.toast' ).is( ':visible' ), true, 'A toast is shown' ); + assert.ok( this.toastSpy.calledOnce, 'A toast is shown' ); } ); }( jQuery, mw.mobileFrontend ) ); -- To view, visit https://gerrit.wikimedia.org/r/229449 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: If37a623f1571645a040c10fc7c5304c7ee0fd332 Gerrit-PatchSet: 32 Gerrit-Project: mediawiki/extensions/MobileFrontend Gerrit-Branch: master Gerrit-Owner: Jdlrobson <jrob...@wikimedia.org> Gerrit-Reviewer: Bmansurov <bmansu...@wikimedia.org> Gerrit-Reviewer: Florianschmidtwelzow <florian.schmidt.stargatewis...@gmail.com> Gerrit-Reviewer: Jdlrobson <jrob...@wikimedia.org> Gerrit-Reviewer: Phuedx <g...@samsmith.io> Gerrit-Reviewer: Robmoen <rm...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits