From d2f6c38fe774eb4ad5bf47803741d303b47371d6 Mon Sep 17 00:00:00 2001 From: Stephen Niedzielski Date: Tue, 10 Jul 2018 15:06:51 -0500 Subject: [PATCH] Update: page issue icons - Fix a bug where the all issues endpoint would incorrectly collect issues from all sections. - Update the page issue iconography. This increases the size of the delivered code and images by 1743 B minified uncompressed according to mw.inspect() (from 16.4 KiB to 18.1 KiB). - Add support for identifying page issue severity based on template CSS classes. - For multiple issues templates, show the highest priority icon. Bug: T191528 Change-Id: Ie0a4c83ec7cfb856ec581d058797109746e3cb99 --- includes/MinervaHooks.php | 4 +- .../templates/ambox.less | 4 + .../download.svg | 0 .../stop-hand.svg | 0 .../issue-content.svg | 1 - .../issue-default.svg | 1 - .../issue-delete.svg | 1 - .../issue-move.svg | 1 - .../issue-pov.svg | 1 - .../issue-protection.svg | 1 - .../issue-speedy.svg | 1 - .../issue-style.svg | 1 - .../issue-generic.svg | 1 + .../issue-severity-medium.svg | 1 + .../issue-type-point-of-view.svg | 1 + .../issue-severity-low.svg | 1 + .../issue-type-move.svg | 1 + .../skins.minerva.scripts/cleanuptemplates.js | 23 ++- .../skins.minerva.scripts/pageIssueParser.js | 168 ++++++++++++++++++ resources/skins.minerva.scripts/utils.js | 44 ----- skin.json | 58 ++++-- .../test_pageIssueParser.js | 124 +++++++++++++ .../qunit/skins.minerva.scripts/test_utils.js | 47 ----- 23 files changed, 364 insertions(+), 121 deletions(-) rename resources/{skins.minerva.icons.images.scripts => skins.minerva.icons.images.scripts.misc}/download.svg (100%) rename resources/{skins.minerva.icons.images.scripts => skins.minerva.icons.images.scripts.misc}/stop-hand.svg (100%) delete mode 100644 resources/skins.minerva.icons.images.scripts/issue-content.svg delete mode 100644 resources/skins.minerva.icons.images.scripts/issue-default.svg delete mode 100644 resources/skins.minerva.icons.images.scripts/issue-delete.svg delete mode 100644 resources/skins.minerva.icons.images.scripts/issue-move.svg delete mode 100644 resources/skins.minerva.icons.images.scripts/issue-pov.svg delete mode 100644 resources/skins.minerva.icons.images.scripts/issue-protection.svg delete mode 100644 resources/skins.minerva.icons.images.scripts/issue-speedy.svg delete mode 100644 resources/skins.minerva.icons.images.scripts/issue-style.svg create mode 100644 resources/skins.minerva.icons.page.issues.default.color/issue-generic.svg create mode 100644 resources/skins.minerva.icons.page.issues.medium.color/issue-severity-medium.svg create mode 100644 resources/skins.minerva.icons.page.issues.medium.color/issue-type-point-of-view.svg create mode 100644 resources/skins.minerva.icons.page.issues.uncolored/issue-severity-low.svg create mode 100644 resources/skins.minerva.icons.page.issues.uncolored/issue-type-move.svg create mode 100644 resources/skins.minerva.scripts/pageIssueParser.js delete mode 100644 resources/skins.minerva.scripts/utils.js create mode 100644 tests/qunit/skins.minerva.scripts/test_pageIssueParser.js delete mode 100644 tests/qunit/skins.minerva.scripts/test_utils.js diff --git a/includes/MinervaHooks.php b/includes/MinervaHooks.php index 9c6f654..d95554c 100644 --- a/includes/MinervaHooks.php +++ b/includes/MinervaHooks.php @@ -82,12 +82,12 @@ class MinervaHooks { 'targets' => [ 'mobile', 'desktop' ], 'scripts' => [ // additional scaffolding (minus initialisation scripts) - 'resources/skins.minerva.scripts/utils.js', + 'resources/skins.minerva.scripts/pageIssueParser.js', 'resources/skins.minerva.scripts/DownloadIcon.js', 'resources/skins.minerva.scripts/AB.js', // test files 'tests/qunit/skins.minerva.scripts/test_DownloadIcon.js', - 'tests/qunit/skins.minerva.scripts/test_utils.js', + 'tests/qunit/skins.minerva.scripts/test_pageIssueParser.js', 'tests/qunit/skins.minerva.scripts/test_AB.js', 'tests/qunit/skins.minerva.notifications.badge/test_NotificationBadge.js' ], diff --git a/resources/skins.minerva.content.styles/templates/ambox.less b/resources/skins.minerva.content.styles/templates/ambox.less index 6ff77c1..a5373f3 100644 --- a/resources/skins.minerva.content.styles/templates/ambox.less +++ b/resources/skins.minerva.content.styles/templates/ambox.less @@ -84,6 +84,10 @@ table.ambox { left: -8px; } + .mw-ui-icon:before { + .background-size(75%, auto); + } + .ambox-learn-more { color: @linkColor; display: inline-block; diff --git a/resources/skins.minerva.icons.images.scripts/download.svg b/resources/skins.minerva.icons.images.scripts.misc/download.svg similarity index 100% rename from resources/skins.minerva.icons.images.scripts/download.svg rename to resources/skins.minerva.icons.images.scripts.misc/download.svg diff --git a/resources/skins.minerva.icons.images.scripts/stop-hand.svg b/resources/skins.minerva.icons.images.scripts.misc/stop-hand.svg similarity index 100% rename from resources/skins.minerva.icons.images.scripts/stop-hand.svg rename to resources/skins.minerva.icons.images.scripts.misc/stop-hand.svg diff --git a/resources/skins.minerva.icons.images.scripts/issue-content.svg b/resources/skins.minerva.icons.images.scripts/issue-content.svg deleted file mode 100644 index 78694c5..0000000 --- a/resources/skins.minerva.icons.images.scripts/issue-content.svg +++ /dev/null @@ -1 +0,0 @@ -ambox-content \ No newline at end of file diff --git a/resources/skins.minerva.icons.images.scripts/issue-default.svg b/resources/skins.minerva.icons.images.scripts/issue-default.svg deleted file mode 100644 index 95373c6..0000000 --- a/resources/skins.minerva.icons.images.scripts/issue-default.svg +++ /dev/null @@ -1 +0,0 @@ -ambox-default \ No newline at end of file diff --git a/resources/skins.minerva.icons.images.scripts/issue-delete.svg b/resources/skins.minerva.icons.images.scripts/issue-delete.svg deleted file mode 100644 index 86d6aaa..0000000 --- a/resources/skins.minerva.icons.images.scripts/issue-delete.svg +++ /dev/null @@ -1 +0,0 @@ -ambox-speedy \ No newline at end of file diff --git a/resources/skins.minerva.icons.images.scripts/issue-move.svg b/resources/skins.minerva.icons.images.scripts/issue-move.svg deleted file mode 100644 index a273342..0000000 --- a/resources/skins.minerva.icons.images.scripts/issue-move.svg +++ /dev/null @@ -1 +0,0 @@ -ambox-move \ No newline at end of file diff --git a/resources/skins.minerva.icons.images.scripts/issue-pov.svg b/resources/skins.minerva.icons.images.scripts/issue-pov.svg deleted file mode 100644 index 088b5c7..0000000 --- a/resources/skins.minerva.icons.images.scripts/issue-pov.svg +++ /dev/null @@ -1 +0,0 @@ -ambox-content.ambox-pov \ No newline at end of file diff --git a/resources/skins.minerva.icons.images.scripts/issue-protection.svg b/resources/skins.minerva.icons.images.scripts/issue-protection.svg deleted file mode 100644 index b3bb12e..0000000 --- a/resources/skins.minerva.icons.images.scripts/issue-protection.svg +++ /dev/null @@ -1 +0,0 @@ -ambox-protection \ No newline at end of file diff --git a/resources/skins.minerva.icons.images.scripts/issue-speedy.svg b/resources/skins.minerva.icons.images.scripts/issue-speedy.svg deleted file mode 100644 index 86d6aaa..0000000 --- a/resources/skins.minerva.icons.images.scripts/issue-speedy.svg +++ /dev/null @@ -1 +0,0 @@ -ambox-speedy \ No newline at end of file diff --git a/resources/skins.minerva.icons.images.scripts/issue-style.svg b/resources/skins.minerva.icons.images.scripts/issue-style.svg deleted file mode 100644 index ef90285..0000000 --- a/resources/skins.minerva.icons.images.scripts/issue-style.svg +++ /dev/null @@ -1 +0,0 @@ -ambox-style \ No newline at end of file diff --git a/resources/skins.minerva.icons.page.issues.default.color/issue-generic.svg b/resources/skins.minerva.icons.page.issues.default.color/issue-generic.svg new file mode 100644 index 0000000..d5db1ed --- /dev/null +++ b/resources/skins.minerva.icons.page.issues.default.color/issue-generic.svg @@ -0,0 +1 @@ +alert \ No newline at end of file diff --git a/resources/skins.minerva.icons.page.issues.medium.color/issue-severity-medium.svg b/resources/skins.minerva.icons.page.issues.medium.color/issue-severity-medium.svg new file mode 100644 index 0000000..733d233 --- /dev/null +++ b/resources/skins.minerva.icons.page.issues.medium.color/issue-severity-medium.svg @@ -0,0 +1 @@ +notice \ No newline at end of file diff --git a/resources/skins.minerva.icons.page.issues.medium.color/issue-type-point-of-view.svg b/resources/skins.minerva.icons.page.issues.medium.color/issue-type-point-of-view.svg new file mode 100644 index 0000000..70f9b88 --- /dev/null +++ b/resources/skins.minerva.icons.page.issues.medium.color/issue-type-point-of-view.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/skins.minerva.icons.page.issues.uncolored/issue-severity-low.svg b/resources/skins.minerva.icons.page.issues.uncolored/issue-severity-low.svg new file mode 100644 index 0000000..f661037 --- /dev/null +++ b/resources/skins.minerva.icons.page.issues.uncolored/issue-severity-low.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/skins.minerva.icons.page.issues.uncolored/issue-type-move.svg b/resources/skins.minerva.icons.page.issues.uncolored/issue-type-move.svg new file mode 100644 index 0000000..a239aa6 --- /dev/null +++ b/resources/skins.minerva.icons.page.issues.uncolored/issue-type-move.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/skins.minerva.scripts/cleanuptemplates.js b/resources/skins.minerva.scripts/cleanuptemplates.js index 24cd2bd..5cdb5c4 100644 --- a/resources/skins.minerva.scripts/cleanuptemplates.js +++ b/resources/skins.minerva.scripts/cleanuptemplates.js @@ -15,8 +15,7 @@ ( function () { var page = M.getCurrentPage(), - getIconFromAmbox = M.require( 'skins.minerva.scripts/utils' ) - .getIconFromAmbox, + pageIssueParser = M.require( 'skins.minerva.scripts/pageIssueParser' ), overlayManager = M.require( 'skins.minerva.scripts/overlayManager' ), CleanupOverlay = M.require( 'mobile.issues/CleanupOverlay' ); @@ -26,13 +25,15 @@ * @param {Object} $box element to extract the message from * @ignore * @typedef {Object} IssueSummary + * @prop {PageIssue} pageIssue * @prop {string} icon HTML string. * @prop {string} text HTML string. * @return {IssueSummary} */ function extractMessage( $box ) { var selector = '.mbox-text, .ambox-text', - $container = $( '
' ); + $container = $( '
' ), + pageIssue; $box.find( selector ).each( function () { var contents, @@ -45,8 +46,11 @@ $( '

' ).html( contents ).appendTo( $container ); } } ); + + pageIssue = pageIssueParser.parse( $box.get( 0 ) ); return { - icon: getIconFromAmbox( $box ).toHtmlString(), + pageIssue: pageIssue, + icon: pageIssue.icon.toHtmlString(), text: $container.html() }; } @@ -85,7 +89,8 @@ selector = 'table.ambox, table.tmbox, table.cmbox, table.fmbox', $metadata = $container.find( selector ), issues = [], - $link; + $link, + severity; // clean it up a little $metadata.find( '.NavFrame' ).remove(); @@ -107,10 +112,12 @@ allIssues[section] = issues; if ( inline ) { + severity = pageIssueParser.maxSeverity( + issues.map( function ( issue ) { return issue.pageIssue; } ) + ); new Icon( { glyphPrefix: 'minerva', - name: 'warning', - isSmall: true + name: pageIssueParser.iconName( $metadata, severity ) } ).prependTo( $metadata.find( '.mbox-text' ) ); $learnMore = $( '' ) .addClass( 'ambox-learn-more' ) @@ -148,7 +155,7 @@ // Note section.all may not exist, depending on the structure of the HTML page. // It will only exist when Minerva has been run in desktop mode. // If it's absent, we'll reduce all the other lists into one. - return section.all || Object.keys( allIssues ).reduce( + return allIssues.all || Object.keys( allIssues ).reduce( function ( all, key ) { return all.concat( allIssues[key] ); }, diff --git a/resources/skins.minerva.scripts/pageIssueParser.js b/resources/skins.minerva.scripts/pageIssueParser.js new file mode 100644 index 0000000..0ad66df --- /dev/null +++ b/resources/skins.minerva.scripts/pageIssueParser.js @@ -0,0 +1,168 @@ +( function ( M ) { + /** + * @typedef PageIssue + * @prop {string} severity A SEVERITY_LEVEL key. + * @prop {Icon} icon + */ + + var Icon = M.require( 'mobile.startup/Icon' ), + // Icons are matching the type selector below use a TYPE_* icon. When unmatched, the icon is + // chosen by severity. Their color is always determined by severity, too. + ICON_NAME = { + // Generic severity icons. + SEVERITY: { + DEFAULT: 'issue-generic', + LOW: 'issue-severity-low', + MEDIUM: 'issue-severity-medium', + HIGH: 'issue-generic' + }, + + // Icons customized by type. + TYPE: { + MOVE: 'issue-type-move', + POINT_OF_VIEW: 'issue-type-point-of-view' + } + }, + ICON_COLOR = { + DEFAULT: 'defaultColor', + LOW: 'lowColor', + MEDIUM: 'mediumColor', + HIGH: 'highColor' + }, + // How severities order and compare from least to greatest. For the multiple issues template, + // severity should be considered the maximum of all its contained issues. + SEVERITY_LEVEL = { + DEFAULT: 0, + LOW: 1, + MEDIUM: 2, + HIGH: 3 + }, + // Match the template's color CSS selector to a severity level concept. Derived via the Ambox + // templates and sub-templates for the top five wikis and tested on page issues inventory: + // - https://people.wikimedia.org/~jdrewniak/page_issues_inventory + // - https://en.wikipedia.org/wiki/Template:Ambox + // - https://es.wikipedia.org/wiki/Plantilla:Metaplantilla_de_avisos + // - https://ja.wikipedia.org/wiki/Template:Ambox + // - https://ru.wikipedia.org/wiki/Шаблон:Ambox + // - https://it.wikipedia.org/wiki/Template:Avviso + // Severity is the class associated with the color. The ResourceLoader config mimics the idea by + // using severity for color variants. + // Severity is determined independently of icons. + // These selectors should be migrated to their templates. + SEVERITY_REGEX = { + LOW: /ambox-style|avviso-stile/, // en, it + MEDIUM: /ambox-content|avviso-contenuto/, // en, it + HIGH: /ambox-speedy|ambox-delete|ambox-serious|avviso-importante/ // en, en, es / ru, it + // ..And everything else that doesn't match should be considered DEFAULT. + }, + // As above but used to identify specific templates requiring icon customization. + TYPE_REGEX = { + MOVE: /ambox-move|ambox-merge|avviso-struttura/, // en, es / ru, it + POINT_OF_VIEW: new RegExp( [ // en + 'ambox-POV', + 'ambox-Advert', + 'ambox-autobiography', + 'ambox-believerpov', + 'ambox-COI', + 'ambox-fanpov', + 'ambox-globalize', + 'ambox-npov-language', + 'ambox-fringe-theories', + 'ambox-systemic-bias' + ].join( '|' ) ) + // ..And everything else that doesn't match is mapped to a "SEVERITY" type. + }, + // Variants supported by specific types. The "severity icon" supports all severities but the + // type icons only support one each by ResourceLoader. + TYPE_SEVERITY = { + MOVE: 'DEFAULT', + POINT_OF_VIEW: 'MEDIUM' + }; + + /** + * @param {Element} box + * @return {string} An SEVERITY_SELECTOR key. + */ + function parseSeverity( box ) { + var severity, identified; + identified = Object.keys( SEVERITY_REGEX ).some( function ( key ) { + var regex = SEVERITY_REGEX[key]; + severity = key; + return regex.test( box.className ); + } ); + return identified ? severity : 'DEFAULT'; + } + + /** + * @param {Element} box + * @param {string} severity An SEVERITY_LEVEL key. + * @return {{name: string, severity: string}} An ICON_NAME. + */ + function parseType( box, severity ) { + var identified, identifiedType; + identified = Object.keys( TYPE_REGEX ).some( function ( type ) { + var regex = TYPE_REGEX[type]; + identifiedType = type; + return regex.test( box.className ); + } ); + return { + name: identified ? ICON_NAME.TYPE[identifiedType] : ICON_NAME.SEVERITY[severity], + severity: identified ? TYPE_SEVERITY[identifiedType] : severity + }; + } + + /** + * @param {Element} box + * @param {string} severity An SEVERITY_LEVEL key. + * @return {string} A severity or type ISSUE_ICON. + */ + function iconName( box, severity ) { + var nameSeverity = parseType( box, severity ); + // The icon with color variant as expected by ResourceLoader, {iconName}-{severityColorVariant}. + return nameSeverity.name + '-' + ICON_COLOR[nameSeverity.severity]; + } + + /** + * @param {PageIssue[]} issues + * @return {string} The greatest SEVERITY_LEVEL key. + */ + function maxSeverity( issues ) { + return issues.reduce( function ( max, issue ) { + return SEVERITY_LEVEL[max] > SEVERITY_LEVEL[issue.severity] ? max : issue.severity; + }, 'DEFAULT' ); + } + + /** + * @param {Element} box + * @return {PageIssue} + */ + function parse( box ) { + var severity = parseSeverity( box ); + return { + severity: severity, + icon: new Icon( { + glyphPrefix: 'minerva', + name: iconName( box, severity ) + } ) + }; + } + + /** + * @module skins.minerva.scripts/utils + */ + M.define( 'skins.minerva.scripts/pageIssueParser', { + /** + * Extract an icon for use with the issue. + * @param {JQuery.Object} $box element to extract the icon from + * @return {Icon} representing the icon + */ + parse: parse, + maxSeverity: maxSeverity, + iconName: iconName, + test: { + parseSeverity: parseSeverity, + parseType: parseType + } + } ); + +}( mw.mobileFrontend ) ); diff --git a/resources/skins.minerva.scripts/utils.js b/resources/skins.minerva.scripts/utils.js deleted file mode 100644 index 7483b0e..0000000 --- a/resources/skins.minerva.scripts/utils.js +++ /dev/null @@ -1,44 +0,0 @@ -( function ( M ) { - - var Icon = M.require( 'mobile.startup/Icon' ); - - function getIconFromAmbox( $box ) { - var glyph, - names = [ - 'speedy', - 'delete', - 'protection', - 'pov', - 'move', - 'style', - 'content' - ]; - - // since objects have no concept of ordering we repeat ourselves here - names.forEach( function ( name ) { - if ( !glyph && $box.hasClass( 'ambox-' + name ) ) { - // with a match, exit - glyph = name; - } - } ); - - glyph = glyph || 'default'; - return new Icon( { - glyphPrefix: 'minerva', - name: 'issue-' + glyph - } ); - } - - /** - * @module skins.minerva.scripts/utils - */ - M.define( 'skins.minerva.scripts/utils', { - /** - * Extract an icon for use with the issue. - * @param {JQuery.Object} $box element to extract the icon from - * @return {Icon} representing the icon - */ - getIconFromAmbox: getIconFromAmbox - } ); - -}( mw.mobileFrontend ) ); diff --git a/skin.json b/skin.json index 6362f7f..489bc77 100644 --- a/skin.json +++ b/skin.json @@ -242,19 +242,54 @@ } }, "skins.minerva.icons.images.scripts": { + "targets": [ + "mobile", + "desktop" + ], + "dependencies": [ + "skins.minerva.icons.images.scripts.misc", + "skins.minerva.icons.page.issues.uncolored", + "skins.minerva.icons.page.issues.default.color", + "skins.minerva.icons.page.issues.medium.color" + ] + }, + "skins.minerva.icons.images.scripts.misc": { "class": "ResourceLoaderImageModule", "selector": ".mw-ui-icon-minerva-{name}:before", "images": { - "issue-speedy": "resources/skins.minerva.icons.images.scripts/issue-speedy.svg", - "issue-delete": "resources/skins.minerva.icons.images.scripts/issue-delete.svg", - "issue-protection": "resources/skins.minerva.icons.images.scripts/issue-protection.svg", - "issue-default": "resources/skins.minerva.icons.images.scripts/issue-default.svg", - "issue-pov": "resources/skins.minerva.icons.images.scripts/issue-pov.svg", - "issue-style": "resources/skins.minerva.icons.images.scripts/issue-style.svg", - "issue-content": "resources/skins.minerva.icons.images.scripts/issue-content.svg", - "issue-move": "resources/skins.minerva.icons.images.scripts/issue-move.svg", - "download": "resources/skins.minerva.icons.images.scripts/download.svg", - "stop-hand": "resources/skins.minerva.icons.images.scripts/stop-hand.svg" + "download": "resources/skins.minerva.icons.images.scripts.misc/download.svg", + "stop-hand": "resources/skins.minerva.icons.images.scripts.misc/stop-hand.svg" + } + }, + "skins.minerva.icons.page.issues.uncolored": { + "class": "ResourceLoaderImageModule", + "selector": ".mw-ui-icon-minerva-{name}:before", + "images": { + "issue-severity-low-lowColor": "resources/skins.minerva.icons.page.issues.uncolored/issue-severity-low.svg", + "issue-type-move-defaultColor": "resources/skins.minerva.icons.page.issues.uncolored/issue-type-move.svg" + } + }, + "skins.minerva.icons.page.issues.default.color": { + "class": "ResourceLoaderImageModule", + "selectorWithoutVariant": ".mw-ui-icon-minerva-{name}-defaultColor:before", + "selectorWithVariant": ".mw-ui-icon-minerva-{name}-{variant}:before", + "defaultColor": "#54595d", + "variants": { + "lowColor": { "color": "#fc3", "global": true }, + "mediumColor": { "color": "#ff5d01", "global": true }, + "highColor": { "color": "#d33", "global": true } + }, + "images": { + "issue-generic": "resources/skins.minerva.icons.page.issues.default.color/issue-generic.svg" + } + }, + "skins.minerva.icons.page.issues.medium.color": { + "class": "ResourceLoaderImageModule", + "selector": ".mw-ui-icon-minerva-{name}-mediumColor:before", + "defaultColor": "#ff5d01", + "images": { + "issue-severity-medium": "resources/skins.minerva.icons.page.issues.medium.color/issue-severity-medium.svg", + "issue-type-point-of-view": "resources/skins.minerva.icons.page.issues.medium.color/issue-type-point-of-view.svg" } }, "skins.minerva.mainPage.styles": { @@ -382,7 +417,7 @@ "resources/skins.minerva.scripts/mobileRedirect.js", "resources/skins.minerva.scripts/search.js", "resources/skins.minerva.scripts/references.js", - "resources/skins.minerva.scripts/utils.js", + "resources/skins.minerva.scripts/pageIssueParser.js", "resources/skins.minerva.scripts/AB.js", "resources/skins.minerva.scripts/cleanuptemplates.js" ] @@ -519,7 +554,6 @@ "resources/skins.minerva.editor/init.js" ] }, - "skins.minerva.backtotop": { "targets": [ "mobile", diff --git a/tests/qunit/skins.minerva.scripts/test_pageIssueParser.js b/tests/qunit/skins.minerva.scripts/test_pageIssueParser.js new file mode 100644 index 0000000..d4b5a13 --- /dev/null +++ b/tests/qunit/skins.minerva.scripts/test_pageIssueParser.js @@ -0,0 +1,124 @@ +( function ( M ) { + var pageIssueParser = M.require( 'skins.minerva.scripts/pageIssueParser' ); + + QUnit.module( 'pageIssueParser' ); + + /** + * @param {string} className + * @return {Element} + */ + function newBox( className ) { + var box = document.createElement( 'div' ); + box.className = className; + return box; + } + + QUnit.test( 'parseSeverity', function ( assert ) { + var tests = [ + [ '', 'DEFAULT', 'empty' ], + [ 'foo', 'DEFAULT', 'unknown' ], + [ 'ambox-style', 'LOW', 'style' ], + [ 'ambox-content', 'MEDIUM', 'content' ], + [ 'ambox-speedy', 'HIGH', 'speedy' ], + [ 'ambox-delete', 'HIGH', 'delete' ], + // Move has an "unknown" severity and falls into DEFAULT. + [ 'ambox-move', 'DEFAULT', 'move' ], + // Point of view uses ambox-content to identify correct severity. + [ 'ambox-content ambox-POV', 'MEDIUM', 'point of view' ] + // Mixed severities such as 'ambox-style ambox-content' are not prioritized. + ]; + tests.forEach( function ( params, i ) { + var + className = params[0], + expect = params[1], + test = params[2], + box = newBox( className ); + assert.strictEqual( + pageIssueParser.test.parseSeverity( box ), + expect, + 'Result should be the correct severity; case ' + i + ' failed: ' + test + '.' + ); + } ); + } ); + + QUnit.test( 'parseType', function ( assert ) { + var tests = [ + [ '', 'DEFAULT', 'issue-generic', 'empty' ], + [ 'foo', 'DEFAULT', 'issue-generic', 'unknown' ], + [ 'ambox-move', 'DEFAULT', 'issue-type-move', 'move' ], + [ 'ambox-POV', 'MEDIUM', 'issue-type-point-of-view', 'point of view' ], + [ '', 'DEFAULT', 'issue-generic', 'Default severity' ], + [ '', 'LOW', 'issue-severity-low', 'Low severity' ], + [ '', 'MEDIUM', 'issue-severity-medium', 'Medium severity' ], + [ '', 'HIGH', 'issue-generic', 'HIGH severity' ] + ]; + tests.forEach( function ( params, i ) { + var + className = params[0], + severity = params[1], + expect = { + name: params[2], + severity: severity + }, + test = params[3], + box = newBox( className ); + assert.propEqual( + pageIssueParser.test.parseType( box, severity ), + expect, + 'Result should be the correct icon type; case ' + i + ' failed: ' + test + '.' + ); + } ); + } ); + + QUnit.test( 'iconName', function ( assert ) { + var tests = [ + [ '', 'DEFAULT', 'issue-generic-defaultColor' ], + [ '', 'LOW', 'issue-severity-low-lowColor' ], + [ '', 'MEDIUM', 'issue-severity-medium-mediumColor' ], + [ '', 'HIGH', 'issue-generic-highColor' ], + [ 'ambox-move', 'DEFAULT', 'issue-type-move-defaultColor' ], + [ 'ambox-POV', 'MEDIUM', 'issue-type-point-of-view-mediumColor' ], + // ResourceLoader only supplies color variants for the generic type. Ensure impossible + // combinations are forbidden. + [ 'ambox-style ambox-POV', 'LOW', 'issue-type-point-of-view-mediumColor' ], + [ 'ambox-content ambox-move', 'MEDIUM', 'issue-type-move-defaultColor' ] + ]; + tests.forEach( function ( params, i ) { + var + className = params[0], + severity = params[1], + expect = params[2], + box = newBox( className ); + assert.strictEqual( + pageIssueParser.iconName( box, severity ), + expect, + 'Result should be the correct ResourceLoader icon name; case ' + i + ' failed: ' + severity + '.' + ); + } ); + } ); + + QUnit.test( 'maxSeverity', function ( assert ) { + var tests = [ + [ [], 'DEFAULT' ], + [ [ 'DEFAULT' ], 'DEFAULT' ], + [ [ 'DEFAULT', 'LOW' ], 'LOW' ], + [ [ 'DEFAULT', 'LOW', 'MEDIUM' ], 'MEDIUM' ], + [ [ 'DEFAULT', 'LOW', 'MEDIUM', 'HIGH' ], 'HIGH' ], + [ [ 'HIGH', 'DEFAULT', 'LOW', 'MEDIUM' ], 'HIGH' ], + [ [ 'DEFAULT', 'HIGH', 'LOW', 'MEDIUM' ], 'HIGH' ] + ]; + tests.forEach( function ( params, i ) { + var + severities = params[0], + expect = params[1]; + assert.strictEqual( + pageIssueParser.maxSeverity( severities.map( function ( severity ) { + return { severity: severity }; + } ) ), + expect, + 'Result should be the highest severity in the array; case ' + i + ' failed.' + ); + } ); + } ); + +}( mw.mobileFrontend ) ); diff --git a/tests/qunit/skins.minerva.scripts/test_utils.js b/tests/qunit/skins.minerva.scripts/test_utils.js deleted file mode 100644 index 3fa4490..0000000 --- a/tests/qunit/skins.minerva.scripts/test_utils.js +++ /dev/null @@ -1,47 +0,0 @@ -( function ( M ) { - var utils = M.require( 'skins.minerva.scripts/utils' ), - getIconFromAmbox = utils.getIconFromAmbox; - - QUnit.module( 'Minerva utils' ); - QUnit.test( 'getIconFromAmbox', function ( assert ) { - var tests = [ - [ - '', 'issue-default' - ], - [ - 'ambox', 'issue-default' - ], - [ - 'ambox-content ambox-speedy', 'issue-speedy' - ], - [ - 'ambox-content ambox-delete', 'issue-delete' - ], - [ - 'ambox-content', 'issue-content' - ], - [ - 'ambox-content ambox-pov', 'issue-pov' - ], - [ - 'ambox-content ambox-style', 'issue-style' - ], - [ - 'ambox-content ambox-move', 'issue-move' - ], - [ - 'ambox-content ambox-protection', 'issue-protection' - ] - ]; - tests.forEach( function ( test, i ) { - var $box = $( '

' ); - $box.addClass( test[0] ); - assert.strictEqual( - getIconFromAmbox( $box ).options.name, - test[1], - i - ); - } ); - } ); - -}( mw.mobileFrontend ) );