diff options
author | jenkins-bot <jenkins-bot@gerrit.wikimedia.org> | 2025-04-07 14:10:31 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@wikimedia.org> | 2025-04-07 14:10:31 +0000 |
commit | 2133f2e9ff3a88ffb0e5b534187fd955c6370429 (patch) | |
tree | 8adbdb6ed392c9b690e3477b3f4ee3ae4a1cb209 | |
parent | d69b6214aded61fcc794367184e8b125067f6264 (diff) | |
parent | bb9f7a62c807b4c186a22fc111de780ddc1de8a9 (diff) | |
download | mediawikicore-2133f2e9ff3a88ffb0e5b534187fd955c6370429.tar.gz mediawikicore-2133f2e9ff3a88ffb0e5b534187fd955c6370429.zip |
Merge "DateFormatter: Fix exception if user date option is not available"
-rw-r--r-- | resources/src/mediawiki.DateFormatter/DateFormatter.js | 33 | ||||
-rw-r--r-- | tests/qunit/resources/mediawiki.DateFormatter/DateFormatter.test.js | 62 |
2 files changed, 79 insertions, 16 deletions
diff --git a/resources/src/mediawiki.DateFormatter/DateFormatter.js b/resources/src/mediawiki.DateFormatter/DateFormatter.js index 4281a1e0163c..f67ba0cca381 100644 --- a/resources/src/mediawiki.DateFormatter/DateFormatter.js +++ b/resources/src/mediawiki.DateFormatter/DateFormatter.js @@ -595,7 +595,7 @@ class DateFormatter { * @return {string} */ formatInternal( style, type, date ) { - const formatName = style ? `${ style } ${ type }` : type; + const formatName = this.makeValidFormatName( style, type ); const formatter = this.getIntlFormatInternal( formatName ); const pattern = this.formats[ formatName ].pattern; if ( pattern ) { @@ -614,6 +614,35 @@ class DateFormatter { } /** + * Validate a style/type and combine them into a single string, falling + * back to the default style if the user style is not available with the + * specified type. + * + * @internal + * @ignore + * + * @param {string|null} style + * @param {string} type + * @return {string} + */ + makeValidFormatName( style, type ) { + if ( !style ) { + return type; + } + // Try the specified style, then the site default style, then "dmy", a + // final fallback which should always exist, because localised date + // format arrays are merged with English, which has "dmy". + for ( const tryStyle of [ style, config.defaultStyle, 'dmy' ] ) { + const name = `${ tryStyle } ${ type }`; + if ( name in this.formats ) { + return name; + } + } + // Perhaps an invalid type, or bad config? + throw new Error( `Unable to find a valid date format for "${ style } ${ type }"` ); + } + + /** * Format a time/date range with a specified style * * @internal @@ -626,7 +655,7 @@ class DateFormatter { * @return {string} */ formatRangeInternal( style, type, date1, date2 ) { - const formatName = style ? `${ style } ${ type }` : type; + const formatName = this.makeValidFormatName( style, type ); const formatter = this.getIntlFormatInternal( formatName ); const pattern = this.formats[ formatName ].rangePattern; if ( pattern ) { diff --git a/tests/qunit/resources/mediawiki.DateFormatter/DateFormatter.test.js b/tests/qunit/resources/mediawiki.DateFormatter/DateFormatter.test.js index be6efbf412b6..a0cda3528b20 100644 --- a/tests/qunit/resources/mediawiki.DateFormatter/DateFormatter.test.js +++ b/tests/qunit/resources/mediawiki.DateFormatter/DateFormatter.test.js @@ -3,17 +3,19 @@ const midnightZulu = new Date( '2025-01-01T00:00:00Z' ); const oneZulu = new Date( '2025-01-01T01:00:00Z' ); const nextDay = new Date( '2025-01-02T00:00:00Z' ); -function fakeOptionsGet( key, fallback ) { - const options = { - timecorrection: 'Offset|60' - }; - return key in options ? options[ key ] : fallback; -} - QUnit.module( 'mediawiki.DateFormatter static functions', ( hooks ) => { + let userOptions; + + function fakeOptionsGet( key, fallback ) { + return key in userOptions ? userOptions[ key ] : fallback; + } hooks.beforeEach( function () { + userOptions = { + timecorrection: 'Offset|60' + }; this.sandbox.stub( mw.user.options, 'get', fakeOptionsGet ); + DateFormatter.clearInstanceCache(); } ); QUnit.test( 'forUser', ( assert ) => { @@ -41,13 +43,36 @@ QUnit.module( 'mediawiki.DateFormatter static functions', ( hooks ) => { assert.strictEqual( instance.formatTime( midnightZulu ), '04:00' ); } ); - QUnit.test( 'formatTimeAndDate', ( assert ) => { - const { formatTimeAndDate } = DateFormatter; - assert.strictEqual( - formatTimeAndDate( midnightZulu ), - '01:00, 1 (january) 2025' - ); - } ); + const formatTimeAndDateCases = [ + { + title: 'null', + dateOption: null, + expected: '01:00, 1 (january) 2025' + }, + { + title: 'mdy', + dateOption: 'mdy', + expected: '01:00, (january) 1, 2025' + }, + { + title: 'bad option', + dateOption: 'bad', + expected: '01:00, 1 (january) 2025' + } + ]; + + QUnit.test.each( + 'formatTimeAndDate', + formatTimeAndDateCases, + ( assert, { dateOption, expected } ) => { + userOptions.date = dateOption; + const { formatTimeAndDate } = DateFormatter; + assert.strictEqual( + formatTimeAndDate( midnightZulu ), + expected + ); + } + ); QUnit.test( 'formatTime', ( assert ) => { const { formatTime } = DateFormatter; @@ -188,9 +213,18 @@ QUnit.module( 'mediawiki.DateFormatter static functions', ( hooks ) => { } ); QUnit.module( 'mediawiki.DateFormatter instance methods', ( hooks ) => { + let userOptions; + + function fakeOptionsGet( key, fallback ) { + userOptions = { + timecorrection: 'Offset|60' + }; + return key in userOptions ? userOptions[ key ] : fallback; + } hooks.beforeEach( function () { this.sandbox.stub( mw.user.options, 'get', fakeOptionsGet ); + DateFormatter.clearInstanceCache(); } ); function getInstance() { |