diff --git a/skins/common/spec/wikibits.spec.js b/skins/common/spec/wikibits.spec.js new file mode 100644 index 000000000000..b91de7004677 --- /dev/null +++ b/skins/common/spec/wikibits.spec.js @@ -0,0 +1,217 @@ +/*global describe, it, expect*/ +describe('wikibits', function() { + 'use strict'; + mw.config = new mw.Map(); + var url1 = '/index.php?title=MediaWiki:UserTags/code.js&action=raw&ctype=text/javascript'; + var url1expect = '/index.php?title=MediaWiki:UserTags.js&action=raw&ctype=text/javascript'; + var url1expect2 = '//dev.wikia.com/index.php?title=MediaWiki:UserTags.js&action=raw&ctype=text/javascript'; + var url2 = '/index.php?title=User:TK-999/common.js&action=raw&ctype=text/javascript'; + var url3 = 'http://dev.wikia.com/index.php?title=MediaWiki:UserTags/code.js&action=raw&ctype=text/javascript'; + var url3expect = '//dev.wikia.com/index.php?title=MediaWiki:UserTags/code.js&action=raw&ctype=text/javascript'; + var url4 = 'https://dev.wikia.com/index.php?title=MediaWiki:UserTags/code.js&action=raw&ctype=text/javascript'; + var url5 = 'http://platform.twitter.com/widgets.js'; + var url6 = '/index.php?title=MediaWiki:WikiaNavigationBarStyle/code.css&action=raw&ctype=text/css'; + var url6expect = '/index.php?title=MediaWiki:WikiaNavigationBarStyle.css&action=raw&ctype=text/css'; + var url7 = 'http://dev.wikia.com/index.php?title=MediaWiki:WikiaNavigationBarStyle/code.css&action=raw&ctype=text/css'; + var url7expect = '//dev.wikia.com/index.php?title=MediaWiki:WikiaNavigationBarStyle/code.css&action=raw&ctype=text/css'; + var url7expect2 = '//dev.wikia.com/index.php?title=MediaWiki:WikiaNavigationBarStyle.css&action=raw&ctype=text/css'; + var url8 = 'http://platform.twitter.com/widgets.css'; + var url9 = '//kocka.wikia.com/index.php?title=MediaWiki:UncategorizedFileListing/code.js&action=raw&ctype=text/javascript'; + var tsScripts = '1539643173'; + var tsReviewed = '1539734490'; + var currentParam = '¤t=' + tsScripts; + var reviewedParam = '&reviewed=' + tsReviewed; + var mediaAttr = 'sampleMedia'; + + it('should define needed global functions', function () { + expect(typeof window.addOnloadHook).toBe('function'); + expect(typeof window.forceReviewedContent).toBe('function'); + expect(typeof window.importScript).toBe('function'); + expect(typeof window.importScriptURI).toBe('function'); + expect(typeof window.importScriptPage).toBe('function'); + expect(typeof window.importStylesheet).toBe('function'); + expect(typeof window.importStylesheetURI).toBe('function'); + expect(typeof window.importStylesheetPage).toBe('function'); + expect(typeof window.loadedScripts).toBe('object'); + }); + + it('should force reviewed content properly', function() { + // Reset mw.config values + mw.config = new mw.Map(); + + // No JavaScript review, nothing should be done + expect(window.forceReviewedContent(url1)).toEqual(url1); + expect(window.forceReviewedContent(url2)).toEqual(url2); + + // Enable Content Review + mw.config.set('wgContentReviewExtEnabled', true); + mw.config.set('wgReviewedScriptsTimestamp', tsReviewed); + mw.config.set('wgScriptsTimestamp', tsScripts); + + // MediaWiki pages should get a 'reviewed' URL parameter + expect(window.forceReviewedContent(url1)).toEqual(url1 + reviewedParam); + expect(window.forceReviewedContent(url2)).toEqual(url2); + + // Enable test mode + mw.config.set('wgContentReviewTestModeEnabled', true); + expect(window.forceReviewedContent(url1)).toEqual(url1 + currentParam); + expect(window.forceReviewedContent(url2)).toEqual(url2); + }); + + it('should import a script by URL properly', function() { + // Reset mw.config values + mw.config = new mw.Map(); + mw.config.set('wgReviewedScriptsTimestamp', tsReviewed); + mw.config.set('wgScriptsTimestamp', tsScripts); + mw.config.set('wgWikiaBaseDomainRegex', '((wikia|fandom)\.com|(wikia|fandom)-dev\.(com|us|pl))'); + + var script = window.importScriptURI(url2); + + // Ensure proper DOM node attributes and insertion + expect(script instanceof Node).toBe(true); + expect(script.nodeName).toBe('SCRIPT'); + expect(script.getAttribute('type')).toEqual('text/javascript'); + expect(script.parentElement).toBe(document.head); + + // Ensure HTTPS isn't enforced when URL isn't insecure + // and that reviewed content isn't forced when not enabled + expect(script.getAttribute('src')).toEqual(url2); + + // Ensure double-loading prevention + expect(window.importScriptURI(url2)).toBe(null); + + // Ensure Content Review forcing works + mw.config.set('wgContentReviewExtEnabled', true); + expect(window.importScriptURI(url1).getAttribute('src')) + .toEqual(url1 + reviewedParam); + + // Ensure HTTPS conversion works + expect(window.importScriptURI(url3).getAttribute('src')) + .toEqual(url3expect + reviewedParam); + + // Ensure HTTPS conversion isn't changing already-HTTPS links + expect(window.importScriptURI(url4).getAttribute('src')) + .toEqual(url4 + reviewedParam); + + // Ensure Content Review and HTTPS conversion aren't affecting + // external imports + expect(window.importScriptURI(url5).getAttribute('src')).toEqual(url5); + }); + + it('should import a script using importScript properly', function() { + // Reset mw.config values + mw.config = new mw.Map(); + mw.config.set('wgReviewedScriptsTimestamp', tsReviewed); + mw.config.set('wgScript', '/index.php'); + mw.config.set('wgScriptsTimestamp', tsScripts); + mw.config.set('wgWikiaBaseDomainRegex', '((wikia|fandom)\.com|(wikia|fandom)-dev\.(com|us|pl))'); + + // Ensure proper URL is being imported + expect(window.importScript('MediaWiki:UserTags/code.js').getAttribute('src')) + .toEqual(url1); + + // Ensure Dev Wiki's /code.js pages are redirected to .js + window.loadedScripts = {}; + mw.config.set('wgCityId', '7931'); + expect(window.importScript('MediaWiki:UserTags/code.js').getAttribute('src')) + .toEqual(url1expect); + }); + + it('should import a script using importScriptPage properly', function() { + // Reset mw.config values + mw.config = new mw.Map(); + mw.config.set('wgReviewedScriptsTimestamp', tsReviewed); + mw.config.set('wgScript', '/index.php'); + mw.config.set('wgScriptsTimestamp', tsScripts); + mw.config.set('wgWikiaBaseDomain', 'wikia.com'); + mw.config.set('wgWikiaBaseDomainRegex', '((wikia|fandom)\.com|(wikia|fandom)-dev\.(com|us|pl))'); + + // Ensure proper local URL is being imported + expect(window.importScriptPage('MediaWiki:UserTags/code.js').getAttribute('src')) + .toEqual(url1); + + // Ensure proper checking is done on the second parameter + window.loadedScripts = {}; + expect(window.importScriptPage('MediaWiki:UserTags/code.js', {}).getAttribute('src')) + .toEqual(url1); + + // Ensure proper local URL is being imported on Dev Wiki + window.loadedScripts = {}; + mw.config.set('wgCityId', '7931'); + expect(window.importScriptPage('MediaWiki:UserTags/code.js').getAttribute('src')) + .toEqual(url1expect); + expect(window.importScriptPage('MediaWiki:UncategorizedFileListing/code.js', 'kocka').getAttribute('src')) + .toEqual(url9); + + // Ensure proper Dev Wiki URL is being imported + window.loadedScripts = {}; + mw.config.set('wgCityId', '177'); + expect(window.importScriptPage('MediaWiki:UserTags/code.js', 'dev').getAttribute('src')) + .toEqual(url1expect2); + }); + + it('should import a stylesheet by URL properly', function() { + // Reset mw.config values + mw.config = new mw.Map(); + mw.config.set('wgWikiaBaseDomainRegex', '((wikia|fandom)\.com|(wikia|fandom)-dev\.(com|us|pl))'); + + var stylesheet = window.importStylesheetURI(url6); + + // Ensure proper DOM node attributes and insertion + expect(stylesheet instanceof Node).toBe(true); + expect(stylesheet.nodeName).toBe('LINK'); + expect(stylesheet.getAttribute('type')).toEqual('text/css'); + expect(stylesheet.getAttribute('rel')).toEqual('stylesheet'); + expect(stylesheet.parentElement).toBe(document.head); + + // Ensure HTTPS isn't enforced on protocol-relative URLs + expect(stylesheet.getAttribute('href')).toEqual(url6); + + var stylesheet2 = window.importStylesheetURI(url7, mediaAttr); + + // Ensure media attribute works + expect(stylesheet2.getAttribute('media')).toEqual(mediaAttr); + expect(stylesheet2.getAttribute('href')).toEqual(url7expect); + + // Ensure nothing is done to external stylesheet URLs + expect(window.importStylesheetURI(url8).getAttribute('href')) + .toEqual(url8); + }); + + it('should import a stylesheet using importStylesheet properly', function() { + // Reset mw.config values + mw.config = new mw.Map(); + mw.config.set('wgScript', '/index.php'); + mw.config.set('wgWikiaBaseDomainRegex', '((wikia|fandom)\.com|(wikia|fandom)-dev\.(com|us|pl))'); + + // Ensure proper local URL is being imported + expect(window.importStylesheet('MediaWiki:WikiaNavigationBarStyle/code.css').getAttribute('href')) + .toEqual(url6); + + // Ensure proper local URL is being imported on Dev Wiki + mw.config.set('wgCityId', '7931'); + expect(window.importStylesheet('MediaWiki:WikiaNavigationBarStyle/code.css').getAttribute('href')) + .toEqual(url6expect); + }); + + it('should import a stylesheet using importStylesheetPage properly', function() { + // Reset mw.config values + mw.config = new mw.Map(); + mw.config.set('wgScript', '/index.php'); + mw.config.set('wgWikiaBaseDomain', 'wikia.com'); + mw.config.set('wgWikiaBaseDomainRegex', '((wikia|fandom)\.com|(wikia|fandom)-dev\.(com|us|pl))'); + + // Ensure proper local URL is being imported + expect(window.importStylesheetPage('MediaWiki:WikiaNavigationBarStyle/code.css').getAttribute('href')) + .toEqual(url6); + + // Ensure proper Dev Wiki URL is being imported + expect(window.importStylesheetPage('MediaWiki:WikiaNavigationBarStyle/code.css', 'dev').getAttribute('href')) + .toEqual(url7expect2); + + // Ensure proper local URL is being imported on Dev Wiki + mw.config.set('wgCityId', '7931'); + expect(window.importStylesheetPage('MediaWiki:WikiaNavigationBarStyle/code.css').getAttribute('href')) + .toEqual(url6expect); + }); +}); diff --git a/skins/common/wikibits.js b/skins/common/wikibits.js index 43e2968f47b3..78aa0a34e1a7 100644 --- a/skins/common/wikibits.js +++ b/skins/common/wikibits.js @@ -1,7 +1,7 @@ /** * MediaWiki legacy wikibits */ -(function(){ +(function() { window.clientPC = navigator.userAgent.toLowerCase(); // Get client info window.is_gecko = /gecko/.test( clientPC ) && @@ -24,21 +24,16 @@ if (webkit_match) { // For accesskeys; note that FF3+ is included here! window.is_ff2 = /firefox\/[2-9]|minefield\/3/.test( clientPC ); -window.ff2_bugs = /firefox\/2/.test( clientPC ); // These aren't used here, but some custom scripts rely on them window.is_ff2_win = is_ff2 && clientPC.indexOf('windows') != -1; window.is_ff2_x11 = is_ff2 && clientPC.indexOf('x11') != -1; -window.is_opera = window.is_opera_preseven = window.is_opera_95 = - window.opera6_bugs = window.opera7_bugs = window.opera95_bugs = false; +window.is_opera = window.is_opera_preseven = window.is_opera_95 = false; if (clientPC.indexOf('opera') != -1) { window.is_opera = true; window.is_opera_preseven = window.opera && !document.childNodes; window.is_opera_seven = window.opera && document.childNodes; window.is_opera_95 = /opera\/(9\.[5-9]|[1-9][0-9])/.test( clientPC ); - window.opera6_bugs = is_opera_preseven; - window.opera7_bugs = is_opera_seven && !is_opera_95; - window.opera95_bugs = /opera\/(9\.5)/.test( clientPC ); } // As recommended by , // avoiding false positives from moronic extensions that append to the IE UA @@ -87,41 +82,60 @@ function maybeMakeProtocolRelative(url) { return url; } -window.importScript = function( page ) { - var uri = mw.config.get( 'wgScript' ) + '?title=' + - mw.util.wikiUrlencode( page ) + +function maybeRedirectDevWikiCodeSubpage(url) { + if ( + url.indexOf(mw.config.get('wgScript')) !== -1 && + ( + (mw.config.get('wgCityId') === '7931' && url.indexOf(mw.config.get('wgScript')) === 0) || + new RegExp('^(https?:)?\\/\\/dev\\.' + mw.config.get('wgWikiaBaseDomainRegex')).test(url) + ) && + /\/code\.(css|js)/.test(url) + ) { + return url.replace(/\/code\.(js|css)/, '.$1') + } + return url; +} + +window.importScript = function(page) { + var uri = mw.config.get('wgScript') + '?title=' + + mw.util.wikiUrlencode(page) + '&action=raw&ctype=text/javascript'; - return importScriptURI( uri ); + uri = maybeRedirectDevWikiCodeSubpage(uri); + return importScriptURI(uri); }; window.loadedScripts = {}; // included-scripts tracker -window.importScriptURI = function( url ) { +window.importScriptURI = function(url) { url = maybeMakeProtocolRelative(forceReviewedContent(url)); - if ( loadedScripts[url] ) { + if (loadedScripts[url]) { return null; } loadedScripts[url] = true; - var s = document.createElement( 'script' ); - s.setAttribute( 'src', url ); - s.setAttribute( 'type', 'text/javascript' ); - document.getElementsByTagName('head')[0].appendChild( s ); + var s = document.createElement('script'); + s.setAttribute('src', url); + s.setAttribute('type', 'text/javascript'); + document.getElementsByTagName('head')[0].appendChild(s); return s; }; -window.importStylesheet = function( page ) { - return importStylesheetURI( mw.config.get( 'wgScript' ) + '?action=raw&ctype=text/css&title=' + mw.util.wikiUrlencode( page ) ); +window.importStylesheet = function(page) { + var uri = mw.config.get('wgScript') + '?title=' + + mw.util.wikiUrlencode(page) + + '&action=raw&ctype=text/css'; + uri = maybeRedirectDevWikiCodeSubpage(uri); + return importStylesheetURI(uri); }; -window.importStylesheetURI = function( url, media ) { - var l = document.createElement( 'link' ); +window.importStylesheetURI = function(url, media) { + var l = document.createElement('link'); l.type = 'text/css'; l.rel = 'stylesheet'; l.href = maybeMakeProtocolRelative(url); - if( media ) { + if (media) { l.media = media; } - document.getElementsByTagName('head')[0].appendChild( l ); + document.getElementsByTagName('head')[0].appendChild(l); return l; }; @@ -138,20 +152,6 @@ window.appendCSS = function( text ) { return s; }; -// Special stylesheet links for Monobook only (see bug 14717) -var skinpath = mw.config.get( 'stylepath' ) + '/' + mw.config.get( 'skin' ); -if ( mw.config.get( 'skin' ) === 'monobook' ) { - if ( opera6_bugs ) { - importStylesheetURI( skinpath + '/Opera6Fixes.css' ); - } else if ( opera7_bugs ) { - importStylesheetURI( skinpath + '/Opera7Fixes.css' ); - } else if ( opera95_bugs ) { - importStylesheetURI( skinpath + '/Opera9Fixes.css' ); - } else if ( ff2_bugs ) { - importStylesheetURI( skinpath + '/FF2Fixes.css' ); - } -} - if ( mw.config.get( 'wgBreakFrames' ) ) { // Un-trap us from framesets if ( window.top != window ) { @@ -715,31 +715,32 @@ function getLabelFor (obj_id) { return false; } -if (skin != 'monaco' && skin != 'oasis') { - //see RT#46116 - if ( !(skin == 'answers' && !window.wgOldAnswerSkin) ) { - addOnloadHook(function() { Wikia.LazyQueue.makeQueue(wgAfterContentAndJS, function(fn) {fn();}); wgAfterContentAndJS.start();} ); - } -} - // http://www.wikia.com/wiki/User:Dantman/global.js // RT#9031 -window.importScriptPage = function( page, server ) { - var url = '/index.php?title=' + encodeURIComponent(page.replace(/ /g,'_')).replace('%2F','/').replace('%3A',':') + '&action=raw&ctype=text/javascript'; - if( typeof server == "string" ) { - if( server.indexOf( '://' ) == -1 && server.substring( 0, 2 ) !== '//' ) url = 'http://' + server + '.' + mw.config.get('wgWikiaBaseDomain') + url; - else url = server + url; +window.importScriptPage = function(page, server) { + var url = mw.config.get('wgScript') + '?title=' + mw.util.wikiUrlencode(page) + '&action=raw&ctype=text/javascript'; + if (typeof server === 'string') { + if (server.indexOf('://') === -1 && server.substring(0, 2) !== '//') { + url = 'http://' + server + '.' + mw.config.get('wgWikiaBaseDomain') + url; + } else { + url = server + url; + } } + url = maybeRedirectDevWikiCodeSubpage(url); return importScriptURI(url); } -window.importStylesheetPage= function( page, server ) { - var url = '/index.php?title=' + encodeURIComponent(page.replace(/ /g,'_')).replace('%2F','/').replace('%3A',':') + '&action=raw&ctype=text/css'; - if( typeof server == "string" ) { - if( server.indexOf( '://' ) == -1 && server.substring( 0, 2 ) !== '//' ) url = 'http://' + server + '.' + mw.config.get('wgWikiaBaseDomain') + url; - else url = server + url; +window.importStylesheetPage = function(page, server) { + var url = mw.config.get('wgScript') + '?title=' + mw.util.wikiUrlencode(page) + '&action=raw&ctype=text/css'; + if (typeof server === 'string') { + if (server.indexOf('://') === -1 && server.substring(0, 2) !== '//') { + url = 'http://' + server + '.' + mw.config.get('wgWikiaBaseDomain') + url; + } else { + url = server + url; + } } + url = maybeRedirectDevWikiCodeSubpage(url); return importStylesheetURI(url); } diff --git a/tests/karma/js-unit.conf.js b/tests/karma/js-unit.conf.js index 559cbe924c8a..fe36731c6077 100644 --- a/tests/karma/js-unit.conf.js +++ b/tests/karma/js-unit.conf.js @@ -25,6 +25,11 @@ module.exports = function (config) { 'resources/wikia/polyfills/bind.js', 'resources/wikia/polyfills/promise.js', 'resources/mediawiki/mediawiki.js', + 'resources/mediawiki/mediawiki.util.js', + + // Skin files + 'skins/common/spec/*.spec.js', + 'skins/common/wikibits.js', //JSMessages 'extensions/wikia/JSMessages/js/JSMessages.js',