Merge "tests: mock should not __clone Database"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 3 Jan 2017 20:58:47 +0000 (20:58 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 3 Jan 2017 20:58:47 +0000 (20:58 +0000)
includes/api/ApiClearHasMsg.php
languages/i18n/en.json
languages/i18n/qqq.json
resources/Resources.php
resources/src/mediawiki.special/mediawiki.special.apisandbox.css
resources/src/mediawiki.special/mediawiki.special.apisandbox.js
resources/src/mediawiki.widgets.datetime/DateTimeFormatter.js
resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js
resources/src/mediawiki.widgets.datetime/DiscordianDateTimeFormatter.js
resources/src/mediawiki.widgets.datetime/ProlepticGregorianDateTimeFormatter.js
tests/phpunit/maintenance/fetchTextTest.php

index 99242a8..a5474b5 100644 (file)
 class ApiClearHasMsg extends ApiBase {
        public function execute() {
                $user = $this->getUser();
-               if ( $this->getRequest()->wasPosted() ) {
-                       $user->setNewtalk( false );
-               } else {
-                       DeferredUpdates::addCallableUpdate( function () use ( $user ) {
-                               $user->setNewtalk( false );
-                       } );
-               }
+               $user->setNewtalk( false );
                $this->getResult()->addValue( null, $this->getModuleName(), 'success' );
        }
 
index 2d7a53e..f2b27fc 100644 (file)
        "apisandbox-sending-request": "Sending API request...",
        "apisandbox-loading-results": "Receiving API results...",
        "apisandbox-results-error": "An error occurred while loading the API query response: $1.",
+       "apisandbox-request-params-json": "JSON parameters:",
        "apisandbox-request-url-label": "Request URL:",
        "apisandbox-request-time": "Request time: {{PLURAL:$1|$1 ms}}",
        "apisandbox-results-fixtoken": "Correct token and resubmit",
index 33e2a8c..99f7679 100644 (file)
        "apisandbox-sending-request": "JavaScript message displayed while the request is being sent.",
        "apisandbox-loading-results": "JavaScript message displayed while the response is being read.",
        "apisandbox-results-error": "Displayed as an error message from JavaScript when the request failed.\n\nParameters:\n* $1 - Error message",
+       "apisandbox-request-params-json": "Label for text field display the request parameters as JSON.",
        "apisandbox-request-url-label": "Label for the text field displaying the URL used to make this request.",
        "apisandbox-request-time": "Label and value for displaying the time taken by the request.\n\nParameters:\n* $1 - Time taken in milliseconds",
        "apisandbox-results-fixtoken": "JavaScript button label",
index ae95c78..92013ec 100644 (file)
@@ -1826,6 +1826,7 @@ return [
                        'apisandbox-sending-request',
                        'apisandbox-loading-results',
                        'apisandbox-results-error',
+                       'apisandbox-request-params-json',
                        'apisandbox-request-url-label',
                        'apisandbox-request-time',
                        'apisandbox-results-fixtoken',
index 99f6c13..707a579 100644 (file)
 .oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator.mw-apisandbox-clickable-indicator {
        cursor: pointer;
 }
+
+.mw-apisandbox-textInputCode .oo-ui-inputWidget-input {
+       font-family: monospace, 'Courier';
+       font-size: 0.8125em;
+       -moz-tab-size: 4;
+       -o-tab-size: 4;
+       tab-size: 4;
+}
index 43321fe..f108e50 100644 (file)
                        }
 
                        $.when.apply( $, deferreds ).done( function () {
+                               var jsonInput;
+
                                if ( $.inArray( false, arguments ) !== -1 ) {
                                        windowManager.openWindow( 'errorAlert', {
                                                title: Util.parseMsg( 'apisandbox-submit-invalid-fields-title' ),
                                                                label: Util.parseMsg( 'apisandbox-request-url-label' )
                                                        }
                                                ).$element,
+                                               new OO.ui.FieldLayout(
+                                                       jsonInput = new OO.ui.TextInputWidget( {
+                                                               classes: [ 'mw-apisandbox-textInputCode' ],
+                                                               readOnly: true,
+                                                               multiline: true,
+                                                               autosize: true,
+                                                               maxRows: 6,
+                                                               value: JSON.stringify( displayParams, null, '\t' )
+                                                       } ), {
+                                                               label: Util.parseMsg( 'apisandbox-request-params-json' )
+                                                       }
+                                               ).$element,
                                                $result
                                        );
                                ApiSandbox.updateUI();
                                booklet.setPage( '|results|' );
 
+                               // Resize the multiline input once visible
+                               jsonInput.adjustSize();
+
                                location.href = oldhash = '#' + query;
 
                                api.post( params, {
index 1793849..ad49a42 100644 (file)
         *  - 'boolean': The field is a boolean.
         *  - 'toggleLocal': The field represents {@link #getLocal this.getLocal()}.
         *    Editing should directly call {@link #toggleLocal this.toggleLocal()}.
+        * @return {boolean} return.calendarComponent Whether this field is part of a calendar, e.g.
+        *  part of the date instead of the time.
         * @return {number} return.size Maximum number of characters in the field (when
         *  the 'intercalary' component is falsey). If 0, the field should be hidden entirely.
         * @return {Object.<string,number>} return.intercalarySize Map from
                                }
                                spec = {
                                        component: null,
+                                       calendarComponent: false,
                                        editable: false,
                                        type: 'static',
                                        value: params.slice( 1 ).join( '|' ),
                                                c = params[ 0 ] === '#' ? '' : ':';
                                                return {
                                                        component: 'zone',
+                                                       calendarComponent: false,
                                                        editable: true,
                                                        type: 'toggleLocal',
                                                        size: 5 + c.length,
                                        case 'full':
                                                spec = {
                                                        component: 'zone',
+                                                       calendarComponent: false,
                                                        editable: true,
                                                        type: 'toggleLocal',
                                                        values: params[ 0 ] === 'short' ? this.shortZones : this.fullZones,
index e9bedf5..3e4c5e2 100644 (file)
                                $field = $( '<span>' )
                                        .width( sz )
                                        .data( 'mw-widgets-datetime-dateTimeInputWidget-placeholder', placeholder );
+                               if ( spec.type !== 'static' ) {
+                                       $field.prop( 'tabIndex', -1 );
+                                       $field.on( 'focus', this.onFieldFocus.bind( this, $field ) );
+                               }
                                if ( spec.type === 'static' ) {
                                        $field.text( spec.value );
                                } else {
         * @param {jQuery.Event} e Focus event
         */
        mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldFocus = function ( $field ) {
+               var spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
+
                if ( !this.isDisabled() ) {
                        if ( this.getValueAsDate() === null ) {
                                this.setValue( this.formatter.getDefaultDate() );
                        }
 
                        if ( this.calendar ) {
-                               this.calendar.toggle( true );
+                               this.calendar.toggle( !!spec.calendarComponent );
                        }
                }
        };
index b280ead..6db2d06 100644 (file)
@@ -67,6 +67,7 @@
                        case 'year|#':
                                spec = {
                                        component: 'Year',
+                                       calendarComponent: true,
                                        type: 'number',
                                        size: 4,
                                        zeropad: false
@@ -76,6 +77,7 @@
                        case 'season|#':
                                spec = {
                                        component: 'Season',
+                                       calendarComponent: true,
                                        type: 'number',
                                        size: 1,
                                        intercalarySize: { 1: 0 },
@@ -86,6 +88,7 @@
                        case 'season|full':
                                spec = {
                                        component: 'Season',
+                                       calendarComponent: true,
                                        type: 'string',
                                        intercalarySize: { 1: 0 },
                                        values: {
                        case 'dow|full':
                                spec = {
                                        component: 'DOW',
+                                       calendarComponent: true,
                                        editable: false,
                                        type: 'string',
                                        intercalarySize: { 1: 0 },
                        case 'day|0':
                                spec = {
                                        component: 'Day',
+                                       calendarComponent: true,
                                        type: 'string',
                                        size: 2,
                                        intercalarySize: { 1: 13 },
                        case 'second|0':
                                spec = {
                                        component: tag.charAt( 0 ).toUpperCase() + tag.slice( 1 ),
+                                       calendarComponent: false,
                                        type: 'number',
                                        size: 2,
                                        zeropad: params[ 0 ] === '0'
                        case 'millisecond|0':
                                spec = {
                                        component: 'Millisecond',
+                                       calendarComponent: false,
                                        type: 'number',
                                        size: 3,
                                        zeropad: params[ 0 ] === '0'
index 9e9b15f..877edba 100644 (file)
@@ -2,7 +2,7 @@
 
        /**
         * Provides various methods needed for formatting dates and times. This
-        * implementation implments the proleptic Gregorian calendar over years
+        * implementation implements the proleptic Gregorian calendar over years
         * 0000–9999.
         *
         * @class
                        case 'year|0':
                                spec = {
                                        component: 'year',
+                                       calendarComponent: true,
                                        type: 'number',
                                        size: 4,
                                        zeropad: params[ 0 ] === '0'
                        case 'month|full':
                                spec = {
                                        component: 'month',
+                                       calendarComponent: true,
                                        type: 'string',
                                        values: params[ 0 ] === 'short' ? this.shortMonthNames : this.fullMonthNames
                                };
                        case 'dow|full':
                                spec = {
                                        component: 'dow',
+                                       calendarComponent: true,
                                        editable: false,
                                        type: 'string',
                                        values: params[ 0 ] === 'short' ? this.shortDayNames : this.fullDayNames
                        case 'month|0':
                        case 'day|#':
                        case 'day|0':
+                               spec = {
+                                       component: tag,
+                                       calendarComponent: true,
+                                       type: 'number',
+                                       size: 2,
+                                       zeropad: params[ 0 ] === '0'
+                               };
+                               break;
+
                        case 'hour|#':
                        case 'hour|0':
                        case 'minute|#':
                        case 'second|0':
                                spec = {
                                        component: tag,
+                                       calendarComponent: false,
                                        type: 'number',
                                        size: 2,
                                        zeropad: params[ 0 ] === '0'
                        case 'hour|012':
                                spec = {
                                        component: 'hour12',
+                                       calendarComponent: false,
                                        type: 'number',
                                        size: 2,
                                        zeropad: params[ 0 ] === '012'
                        case 'hour|period':
                                spec = {
                                        component: 'hour12period',
+                                       calendarComponent: false,
                                        type: 'boolean',
                                        values: this.hour12Periods
                                };
                        case 'millisecond|0':
                                spec = {
                                        component: 'millisecond',
+                                       calendarComponent: false,
                                        type: 'number',
                                        size: 3,
                                        zeropad: params[ 0 ] === '0'
index 2e35eca..5a28bfb 100644 (file)
@@ -75,11 +75,11 @@ class FetchTextTest extends MediaWikiTestCase {
 
        // We add 5 Revisions for this test. Their corresponding text id's
        // are stored in the following 5 variables.
-       private $textId1;
-       private $textId2;
-       private $textId3;
-       private $textId4;
-       private $textId5;
+       protected static $textId1;
+       protected static $textId2;
+       protected static $textId3;
+       protected static $textId4;
+       protected static $textId5;
 
        /**
         * @var Exception|null As the current MediaWikiTestCase::run is not
@@ -88,7 +88,7 @@ class FetchTextTest extends MediaWikiTestCase {
         * we catch the exception and store it until we are in setUp and may
         * finally rethrow the exception without crashing the test suite.
         */
-       private $exceptionFromAddDBData;
+       protected static $exceptionFromAddDBDataOnce;
 
        /**
         * @var FetchText The (mocked) FetchText that is to test
@@ -123,17 +123,13 @@ class FetchTextTest extends MediaWikiTestCase {
                throw new MWException( "Could not determine text id" );
        }
 
-       function addDBData() {
-               $this->tablesUsed[] = 'page';
-               $this->tablesUsed[] = 'revision';
-               $this->tablesUsed[] = 'text';
-
+       function addDBDataOnce() {
                $wikitextNamespace = $this->getDefaultWikitextNS();
 
                try {
                        $title = Title::newFromText( 'FetchTextTestPage1', $wikitextNamespace );
                        $page = WikiPage::factory( $title );
-                       $this->textId1 = $this->addRevision(
+                       self::$textId1 = $this->addRevision(
                                $page,
                                "FetchTextTestPage1Text1",
                                "FetchTextTestPage1Summary1"
@@ -141,30 +137,30 @@ class FetchTextTest extends MediaWikiTestCase {
 
                        $title = Title::newFromText( 'FetchTextTestPage2', $wikitextNamespace );
                        $page = WikiPage::factory( $title );
-                       $this->textId2 = $this->addRevision(
+                       self::$textId2 = $this->addRevision(
                                $page,
                                "FetchTextTestPage2Text1",
                                "FetchTextTestPage2Summary1"
                        );
-                       $this->textId3 = $this->addRevision(
+                       self::$textId3 = $this->addRevision(
                                $page,
                                "FetchTextTestPage2Text2",
                                "FetchTextTestPage2Summary2"
                        );
-                       $this->textId4 = $this->addRevision(
+                       self::$textId4 = $this->addRevision(
                                $page,
                                "FetchTextTestPage2Text3",
                                "FetchTextTestPage2Summary3"
                        );
-                       $this->textId5 = $this->addRevision(
+                       self::$textId5 = $this->addRevision(
                                $page,
                                "FetchTextTestPage2Text4 some additional Text  ",
                                "FetchTextTestPage2Summary4 extra "
                        );
                } catch ( Exception $e ) {
                        // We'd love to pass $e directly. However, ... see
-                       // documentation of exceptionFromAddDBData
-                       $this->exceptionFromAddDBData = $e;
+                       // documentation of exceptionFromAddDBDataOnce
+                       self::$exceptionFromAddDBDataOnce = $e;
                }
        }
 
@@ -172,8 +168,8 @@ class FetchTextTest extends MediaWikiTestCase {
                parent::setUp();
 
                // Check if any Exception is stored for rethrowing from addDBData
-               if ( $this->exceptionFromAddDBData !== null ) {
-                       throw $this->exceptionFromAddDBData;
+               if ( self::$exceptionFromAddDBDataOnce !== null ) {
+                       throw self::$exceptionFromAddDBDataOnce;
                }
 
                $this->fetchText = new SemiMockedFetchText();
@@ -198,24 +194,29 @@ class FetchTextTest extends MediaWikiTestCase {
        // provider would not know the required ids.
 
        function testExistingSimple() {
-               $this->assertFilter( $this->textId2,
-                       $this->textId2 . "\n23\nFetchTextTestPage2Text1" );
+               $this->assertFilter( self::$textId2,
+                       self::$textId2 . "\n23\nFetchTextTestPage2Text1" );
        }
 
        function testExistingSimpleWithNewline() {
-               $this->assertFilter( $this->textId2 . "\n",
-                       $this->textId2 . "\n23\nFetchTextTestPage2Text1" );
+               $this->assertFilter( self::$textId2 . "\n",
+                       self::$textId2 . "\n23\nFetchTextTestPage2Text1" );
        }
 
        function testExistingSeveral() {
-               $this->assertFilter( "$this->textId1\n$this->textId5\n"
-                               . "$this->textId3\n$this->textId3",
-                       implode( "", [
-                               $this->textId1 . "\n23\nFetchTextTestPage1Text1",
-                               $this->textId5 . "\n44\nFetchTextTestPage2Text4 "
+               $this->assertFilter(
+                       join( "\n", [
+                               self::$textId1,
+                               self::$textId5,
+                               self::$textId3,
+                               self::$textId3,
+                       ] ),
+                       implode( '', [
+                               self::$textId1 . "\n23\nFetchTextTestPage1Text1",
+                               self::$textId5 . "\n44\nFetchTextTestPage2Text4 "
                                        . "some additional Text",
-                               $this->textId3 . "\n23\nFetchTextTestPage2Text2",
-                               $this->textId3 . "\n23\nFetchTextTestPage2Text2"
+                               self::$textId3 . "\n23\nFetchTextTestPage2Text2",
+                               self::$textId3 . "\n23\nFetchTextTestPage2Text2"
                        ] ) );
        }
 
@@ -224,7 +225,7 @@ class FetchTextTest extends MediaWikiTestCase {
        }
 
        function testNonExisting() {
-               $this->assertFilter( $this->textId5 + 10, ( $this->textId5 + 10 ) . "\n-1\n" );
+               $this->assertFilter( self::$textId5 + 10, ( self::$textId5 + 10 ) . "\n-1\n" );
        }
 
        function testNegativeInteger() {
@@ -233,13 +234,13 @@ class FetchTextTest extends MediaWikiTestCase {
 
        function testFloatingPointNumberExisting() {
                // float -> int -> revision
-               $this->assertFilter( $this->textId3 + 0.14159,
-                       $this->textId3 . "\n23\nFetchTextTestPage2Text2" );
+               $this->assertFilter( self::$textId3 + 0.14159,
+                       self::$textId3 . "\n23\nFetchTextTestPage2Text2" );
        }
 
        function testFloatingPointNumberNonExisting() {
-               $this->assertFilter( $this->textId5 + 3.14159,
-                       ( $this->textId5 + 3 ) . "\n-1\n" );
+               $this->assertFilter( self::$textId5 + 3.14159,
+                       ( self::$textId5 + 3 ) . "\n-1\n" );
        }
 
        function testCharacters() {
@@ -247,15 +248,15 @@ class FetchTextTest extends MediaWikiTestCase {
        }
 
        function testMix() {
-               $this->assertFilter( "ab\n" . $this->textId4 . ".5cd\n\nefg\n" . $this->textId2
-                               . "\n" . $this->textId3,
+               $this->assertFilter( "ab\n" . self::$textId4 . ".5cd\n\nefg\n" . self::$textId2
+                               . "\n" . self::$textId3,
                        implode( "", [
                                "0\n-1\n",
-                               $this->textId4 . "\n23\nFetchTextTestPage2Text3",
+                               self::$textId4 . "\n23\nFetchTextTestPage2Text3",
                                "0\n-1\n",
                                "0\n-1\n",
-                               $this->textId2 . "\n23\nFetchTextTestPage2Text1",
-                               $this->textId3 . "\n23\nFetchTextTestPage2Text2"
+                               self::$textId2 . "\n23\nFetchTextTestPage2Text1",
+                               self::$textId3 . "\n23\nFetchTextTestPage2Text2"
                        ] ) );
        }
 }