WordPress.org

Make WordPress Core

Changeset 49275


Ignore:
Timestamp:
10/22/2020 04:03:25 AM (15 months ago)
Author:
tellyworth
Message:

Community Events: Display dates and times in the user's time zone.

Fixes #51130
Merges [49145], [49146], [49147], [49152], and [49201] to the 5.5 branch.
Props sippis, hlashbrooke, audrasjb, Rarst, iandunn

Location:
branches/5.5
Files:
7 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/5.5

  • branches/5.5/src/js/_enqueues/wp/dashboard.js

    r48168 r49275  
    267267
    268268    var communityEventsData = window.communityEventsData || {},
     269        dateI18n = wp.date.dateI18n,
     270        format = wp.date.format,
     271        sprintf = wp.i18n.sprintf,
     272        __ = wp.i18n.__,
     273        _x = wp.i18n._x,
    269274        app;
    270275
     
    442447                    app.renderEventsTemplate({
    443448                        'location' : false,
     449                        'events'   : [],
    444450                        'error'    : true
    445451                    }, initiatedBy );
     
    465471                $locationMessage = $( '#community-events-location-message' ),
    466472                $results         = $( '.community-events-results' );
     473
     474            templateParams.events = app.populateDynamicEventFields(
     475                templateParams.events,
     476                communityEventsData.time_format
     477            );
    467478
    468479            /*
     
    577588                app.toggleLocationForm( 'show' );
    578589            }
     590        },
     591
     592        /**
     593         * Populate event fields that have to be calculated on the fly.
     594         *
     595         * These can't be stored in the database, because they're dependent on
     596         * the user's current time zone, locale, etc.
     597         *
     598         * @since 5.5.2
     599         *
     600         * @param {Array}  rawEvents  The events that should have dynamic fields added to them.
     601         * @param {string} timeFormat A time format acceptable by `wp.date.dateI18n()`.
     602         *
     603         * @returns {Array}
     604         */
     605        populateDynamicEventFields: function( rawEvents, timeFormat ) {
     606            // Clone the parameter to avoid mutating it, so that this can remain a pure function.
     607            var populatedEvents = JSON.parse( JSON.stringify( rawEvents ) );
     608
     609            $.each( populatedEvents, function( index, event ) {
     610                var timeZone = app.getTimeZone( event.start_unix_timestamp * 1000 );
     611
     612                event.user_formatted_date = app.getFormattedDate(
     613                    event.start_unix_timestamp * 1000,
     614                    event.end_unix_timestamp * 1000,
     615                    timeZone
     616                );
     617
     618                event.user_formatted_time = dateI18n(
     619                    timeFormat,
     620                    event.start_unix_timestamp * 1000,
     621                    timeZone
     622                );
     623
     624                event.timeZoneAbbreviation = app.getTimeZoneAbbreviation( event.start_unix_timestamp * 1000 );
     625            } );
     626
     627            return populatedEvents;
     628        },
     629
     630        /**
     631         * Returns the user's local/browser time zone, in a form suitable for `wp.date.i18n()`.
     632         *
     633         * @since 5.5.2
     634         *
     635         * @param startTimestamp
     636         *
     637         * @returns {string|number}
     638         */
     639        getTimeZone: function( startTimestamp ) {
     640            /*
     641             * Prefer a name like `Europe/Helsinki`, since that automatically tracks daylight savings. This
     642             * doesn't need to take `startTimestamp` into account for that reason.
     643             */
     644            var timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
     645
     646            /*
     647             * Fall back to an offset for IE11, which declares the property but doesn't assign a value.
     648             */
     649            if ( 'undefined' === typeof timeZone ) {
     650                /*
     651                 * It's important to use the _event_ time, not the _current_
     652                 * time, so that daylight savings time is accounted for.
     653                 */
     654                timeZone = app.getFlippedTimeZoneOffset( startTimestamp );
     655            }
     656
     657            return timeZone;
     658        },
     659
     660        /**
     661         * Get intuitive time zone offset.
     662         *
     663         * `Data.prototype.getTimezoneOffset()` returns a positive value for time zones
     664         * that are _behind_ UTC, and a _negative_ value for ones that are ahead.
     665         *
     666         * See https://stackoverflow.com/questions/21102435/why-does-javascript-date-gettimezoneoffset-consider-0500-as-a-positive-off.
     667         *
     668         * @since 5.5.2
     669         *
     670         * @param {number} startTimestamp
     671         *
     672         * @returns {number}
     673         */
     674        getFlippedTimeZoneOffset: function( startTimestamp ) {
     675            return new Date( startTimestamp ).getTimezoneOffset() * -1;
     676        },
     677
     678        /**
     679         * Get a short time zone name, like `PST`.
     680         *
     681         * @since 5.5.2
     682         *
     683         * @param {number} startTimestamp
     684         *
     685         * @returns {string}
     686         */
     687        getTimeZoneAbbreviation: function( startTimestamp ) {
     688            var timeZoneAbbreviation,
     689                eventDateTime = new Date( startTimestamp );
     690
     691            /*
     692             * Leaving the `locales` argument undefined is important, so that the browser
     693             * displays the abbreviation that's most appropriate for the current locale. For
     694             * some that will be `UTC{+|-}{n}`, and for others it will be a code like `PST`.
     695             *
     696             * This doesn't need to take `startTimestamp` into account, because a name like
     697             * `America/Chicago` automatically tracks daylight savings.
     698             */
     699            var shortTimeStringParts = eventDateTime.toLocaleTimeString( undefined, { timeZoneName : 'short' } ).split( ' ' );
     700
     701            if ( 3 === shortTimeStringParts.length ) {
     702                timeZoneAbbreviation = shortTimeStringParts[2];
     703            }
     704
     705            if ( 'undefined' === typeof timeZoneAbbreviation ) {
     706                /*
     707                 * It's important to use the _event_ time, not the _current_
     708                 * time, so that daylight savings time is accounted for.
     709                 */
     710                var timeZoneOffset = app.getFlippedTimeZoneOffset( startTimestamp ),
     711                    sign = -1 === Math.sign( timeZoneOffset ) ? '' : '+';
     712
     713                // translators: Used as part of a string like `GMT+5` in the Events Widget.
     714                timeZoneAbbreviation = _x( 'GMT', 'Events widget offset prefix' ) + sign + ( timeZoneOffset / 60 );
     715            }
     716
     717            return timeZoneAbbreviation;
     718        },
     719
     720        /**
     721         * Format a start/end date in the user's local time zone and locale.
     722         *
     723         * @since 5.5.2
     724         *
     725         * @param {int}    startDate   The Unix timestamp in milliseconds when the the event starts.
     726         * @param {int}    endDate     The Unix timestamp in milliseconds when the the event ends.
     727         * @param {string} timeZone    A time zone string or offset which is parsable by `wp.date.i18n()`.
     728         *
     729         * @returns {string}
     730         */
     731        getFormattedDate: function( startDate, endDate, timeZone ) {
     732            var formattedDate;
     733
     734            /*
     735             * The `date_format` option is not used because it's important
     736             * in this context to keep the day of the week in the displayed date,
     737             * so that users can tell at a glance if the event is on a day they
     738             * are available, without having to open the link.
     739             *
     740             * The case of crossing a year boundary is intentionally not handled.
     741             * It's so rare in practice that it's not worth the complexity
     742             * tradeoff. The _ending_ year should be passed to
     743             * `multiple_month_event`, though, just in case.
     744             */
     745            /* translators: Date format for upcoming events on the dashboard. Include the day of the week. See https://www.php.net/manual/datetime.format.php */
     746            var singleDayEvent = __( 'l, M j, Y' ),
     747                /* translators: Date string for upcoming events. 1: Month, 2: Starting day, 3: Ending day, 4: Year. */
     748                multipleDayEvent = __( '%1$s %2$d–%3$d, %4$d' ),
     749                /* translators: Date string for upcoming events. 1: Starting month, 2: Starting day, 3: Ending month, 4: Ending day, 5: Ending year. */
     750                multipleMonthEvent = __( '%1$s %2$d – %3$s %4$d, %5$d' );
     751
     752            // Detect single-day events.
     753            if ( ! endDate || format( 'Y-m-d', startDate ) === format( 'Y-m-d', endDate ) ) {
     754                formattedDate = dateI18n( singleDayEvent, startDate, timeZone );
     755
     756            // Multiple day events.
     757            } else if ( format( 'Y-m', startDate ) === format( 'Y-m', endDate ) ) {
     758                formattedDate = sprintf(
     759                    multipleDayEvent,
     760                    dateI18n( _x( 'F', 'upcoming events month format' ), startDate, timeZone ),
     761                    dateI18n( _x( 'j', 'upcoming events day format' ), startDate, timeZone ),
     762                    dateI18n( _x( 'j', 'upcoming events day format' ), endDate, timeZone ),
     763                    dateI18n( _x( 'Y', 'upcoming events year format' ), endDate, timeZone )
     764                );
     765
     766            // Multi-day events that cross a month boundary.
     767            } else {
     768                formattedDate = sprintf(
     769                    multipleMonthEvent,
     770                    dateI18n( _x( 'F', 'upcoming events month format' ), startDate, timeZone ),
     771                    dateI18n( _x( 'j', 'upcoming events day format' ), startDate, timeZone ),
     772                    dateI18n( _x( 'F', 'upcoming events month format' ), endDate, timeZone ),
     773                    dateI18n( _x( 'j', 'upcoming events day format' ), endDate, timeZone ),
     774                    dateI18n( _x( 'Y', 'upcoming events year format' ), endDate, timeZone )
     775                );
     776            }
     777
     778            return formattedDate;
    579779        }
    580780    };
  • branches/5.5/src/wp-admin/includes/class-wp-community-events.php

    r48110 r49275  
    7878     *
    7979     * @since 4.8.0
     80     * @since 5.5.2 Response no longer contains formatted date field. They're added
     81     *              in `wp.communityEvents.populateDynamicEventFields()` now.
    8082     *
    8183     * @param string $location_search Optional. City name to help determine the location.
     
    159161            }
    160162
     163            /*
     164             * Store the raw response, because events will expire before the cache does.
     165             * The response will need to be processed every page load.
     166             */
    161167            $this->cache_events( $response_body, $expiration );
    162168
    163             $response_body = $this->trim_events( $response_body );
    164             $response_body = $this->format_event_data_time( $response_body );
     169            $response_body['events'] = $this->trim_events( $response_body['events'] );
    165170
    166171            return $response_body;
     
    341346     *
    342347     * @since 4.8.0
     348     * @since 5.5.2 Response no longer contains formatted date field. They're added
     349     *              in `wp.communityEvents.populateDynamicEventFields()` now.
    343350     *
    344351     * @return array|false An array containing `location` and `events` items
     
    347354    public function get_cached_events() {
    348355        $cached_response = get_site_transient( $this->get_events_transient_key( $this->user_location ) );
    349         $cached_response = $this->trim_events( $cached_response );
    350 
    351         return $this->format_event_data_time( $cached_response );
     356
     357        if ( isset( $cached_response['events'] ) ) {
     358            $cached_response['events'] = $this->trim_events( $cached_response['events'] );
     359        }
     360
     361        return $cached_response;
    352362    }
    353363
     
    361371     *
    362372     * @since 4.8.0
     373     * @deprecated 5.6.0 No longer used in core.
    363374     *
    364375     * @param array $response_body The response which contains the events.
     
    366377     */
    367378    protected function format_event_data_time( $response_body ) {
     379        _deprecated_function(
     380            __METHOD__,
     381            '5.5.2',
     382            'This is no longer used by core, and only kept for backward compatibility.'
     383        );
     384
    368385        if ( isset( $response_body['events'] ) ) {
    369386            foreach ( $response_body['events'] as $key => $event ) {
     
    436453     * @since 4.8.0
    437454     * @since 4.9.7 Stick a WordCamp to the final list.
    438      *
    439      * @param array $response_body The response body which contains the events.
     455     * @since 5.5.2 Accepts and returns only the events, rather than an entire HTTP response.
     456     *
     457     * @param array $events The events that will be prepared.
    440458     * @return array The response body with events trimmed.
    441459     */
    442     protected function trim_events( $response_body ) {
    443         if ( isset( $response_body['events'] ) ) {
    444             $wordcamps = array();
    445             $today     = current_time( 'Y-m-d' );
    446 
    447             foreach ( $response_body['events'] as $key => $event ) {
    448                 /*
    449                  * Skip WordCamps, because they might be multi-day events.
    450                  * Save a copy so they can be pinned later.
    451                  */
    452                 if ( 'wordcamp' === $event['type'] ) {
    453                     $wordcamps[] = $event;
    454                     continue;
    455                 }
    456 
    457                 // We don't get accurate time with timezone from API, so we only take the date part (Y-m-d).
    458                 $event_date = substr( $event['date'], 0, 10 );
    459 
    460                 if ( $today > $event_date ) {
    461                     unset( $response_body['events'][ $key ] );
    462                 }
    463             }
    464 
    465             $response_body['events'] = array_slice( $response_body['events'], 0, 3 );
    466             $trimmed_event_types     = wp_list_pluck( $response_body['events'], 'type' );
    467 
    468             // Make sure the soonest upcoming WordCamp is pinned in the list.
    469             if ( ! in_array( 'wordcamp', $trimmed_event_types, true ) && $wordcamps ) {
    470                 array_pop( $response_body['events'] );
    471                 array_push( $response_body['events'], $wordcamps[0] );
    472             }
    473         }
    474 
    475         return $response_body;
     460    protected function trim_events( array $events ) {
     461        $future_events = array();
     462
     463        foreach ( $events as $event ) {
     464            /*
     465             * The API's `date` and `end_date` fields are in the _event's_ local timezone, but UTC is needed so
     466             * it can be converted to the _user's_ local time.
     467             */
     468            $end_time = (int) $event['end_unix_timestamp'];
     469
     470            if ( time() < $end_time ) {
     471                array_push( $future_events, $event );
     472            }
     473        }
     474
     475        $future_wordcamps = array_filter(
     476            $future_events,
     477            function( $wordcamp ) {
     478                return 'wordcamp' === $wordcamp['type'];
     479            }
     480        );
     481
     482        $future_wordcamps    = array_values( $future_wordcamps ); // Remove gaps in indices.
     483        $trimmed_events      = array_slice( $future_events, 0, 3 );
     484        $trimmed_event_types = wp_list_pluck( $trimmed_events, 'type' );
     485
     486        // Make sure the soonest upcoming WordCamp is pinned in the list.
     487        if ( $future_wordcamps && ! in_array( 'wordcamp', $trimmed_event_types, true ) ) {
     488            array_pop( $trimmed_events );
     489            array_push( $trimmed_events, $future_wordcamps[0] );
     490        }
     491
     492        return $trimmed_events;
    476493    }
    477494
  • branches/5.5/src/wp-admin/includes/dashboard.php

    r48586 r49275  
    13801380
    13811381                <div class="event-date-time">
    1382                     <span class="event-date">{{ event.formatted_date }}</span>
     1382                    <span class="event-date">{{ event.user_formatted_date }}</span>
    13831383                    <# if ( 'meetup' === event.type ) { #>
    1384                         <span class="event-time">{{ event.formatted_time }}</span>
     1384                        <span class="event-time">
     1385                            {{ event.user_formatted_time }} {{ event.timeZoneAbbreviation }}
     1386                        </span>
    13851387                    <# } #>
    13861388                </div>
  • branches/5.5/src/wp-includes/script-loader.php

    r48925 r49275  
    12781278        $scripts->set_translations( 'wp-color-picker' );
    12791279
    1280         $scripts->add( 'dashboard', "/wp-admin/js/dashboard$suffix.js", array( 'jquery', 'admin-comments', 'postbox', 'wp-util', 'wp-a11y' ), false, 1 );
     1280        $scripts->add( 'dashboard', "/wp-admin/js/dashboard$suffix.js", array( 'jquery', 'admin-comments', 'postbox', 'wp-util', 'wp-a11y', 'wp-date' ), false, 1 );
     1281        $scripts->set_translations( 'dashboard' );
    12811282
    12821283        $scripts->add( 'list-revisions', "/wp-includes/js/wp-list-revisions$suffix.js" );
     
    17231724        'communityEventsData',
    17241725        array(
    1725             'nonce' => wp_create_nonce( 'community_events' ),
    1726             'cache' => $events_client->get_cached_events(),
    1727 
    1728             'l10n'  => array(
     1726            'nonce'       => wp_create_nonce( 'community_events' ),
     1727            'cache'       => $events_client->get_cached_events(),
     1728            'time_format' => get_option( 'time_format' ),
     1729
     1730            'l10n'        => array(
    17291731                'enter_closest_city'              => __( 'Enter your closest city to find nearby events.' ),
    17301732                'error_occurred_please_try_again' => __( 'An error occurred. Please try again.' ),
  • branches/5.5/tests/phpunit/tests/admin/includesCommunityEvents.php

    r48576 r49275  
    154154    /**
    155155     * Test: With a valid response, get_events() should return an associative array containing a location array and
    156      * an events array with individual events that have formatted time and date.
     156     * an events array with individual events that have Unix start/end timestamps.
    157157     *
    158158     * @since 4.8.0
     
    165165        $this->assertNotWPError( $response );
    166166        $this->assertEqualSetsWithIndex( $this->get_user_location(), $response['location'] );
    167         $this->assertEquals( gmdate( 'l, M j, Y', strtotime( 'next Sunday 1pm' ) ), $response['events'][0]['formatted_date'] );
    168         $this->assertEquals( '1:00 pm', $response['events'][0]['formatted_time'] );
     167        $this->assertSame( strtotime( 'next Sunday 1pm' ), $response['events'][0]['start_unix_timestamp'] );
     168        $this->assertSame( strtotime( 'next Sunday 2pm' ), $response['events'][0]['end_unix_timestamp'] );
    169169
    170170        remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response' ) );
     
    172172
    173173    /**
    174      * Test: get_cached_events() should return the same data as get_events(), including formatted time
    175      * and date values for each event.
     174     * Test: `get_cached_events()` should return the same data as get_events(), including Unix start/end
     175     * timestamps for each event.
    176176     *
    177177     * @since 4.8.0
     
    186186        $this->assertNotWPError( $cached_events );
    187187        $this->assertEqualSetsWithIndex( $this->get_user_location(), $cached_events['location'] );
    188         $this->assertEquals( gmdate( 'l, M j, Y', strtotime( 'next Sunday 1pm' ) ), $cached_events['events'][0]['formatted_date'] );
    189         $this->assertEquals( '1:00 pm', $cached_events['events'][0]['formatted_time'] );
     188        $this->assertSame( strtotime( 'next Sunday 1pm' ), $cached_events['events'][0]['start_unix_timestamp'] );
     189        $this->assertSame( strtotime( 'next Sunday 2pm' ), $cached_events['events'][0]['end_unix_timestamp'] );
    190190
    191191        remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response' ) );
     
    205205                array(
    206206                    'location' => $this->get_user_location(),
    207                     'events'   => array(
    208                         array(
    209                             'type'       => 'meetup',
    210                             'title'      => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
    211                             'url'        => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
    212                             'meetup'     => 'The East Bay WordPress Meetup Group',
    213                             'meetup_url' => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
    214                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Sunday 1pm' ) ),
    215                             'location'   => array(
    216                                 'location'  => 'Oakland, CA, USA',
    217                                 'country'   => 'us',
    218                                 'latitude'  => 37.808453,
    219                                 'longitude' => -122.26593,
    220                             ),
    221                         ),
    222                         array(
    223                             'type'       => 'meetup',
    224                             'title'      => 'Part 3- Site Maintenance - Tools to Make It Easy',
    225                             'url'        => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
    226                             'meetup'     => 'WordPress Bay Area Foothills Group',
    227                             'meetup_url' => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
    228                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Wednesday 1:30pm' ) ),
    229                             'location'   => array(
    230                                 'location'  => 'Milpitas, CA, USA',
    231                                 'country'   => 'us',
    232                                 'latitude'  => 37.432813,
    233                                 'longitude' => -121.907095,
    234                             ),
    235                         ),
    236                         array(
    237                             'type'       => 'wordcamp',
    238                             'title'      => 'WordCamp Kansas City',
    239                             'url'        => 'https://2017.kansascity.wordcamp.org',
    240                             'meetup'     => null,
    241                             'meetup_url' => null,
    242                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Saturday' ) ),
    243                             'location'   => array(
    244                                 'location'  => 'Kansas City, MO',
    245                                 'country'   => 'US',
    246                                 'latitude'  => 39.0392325,
    247                                 'longitude' => -94.577076,
    248                             ),
    249                         ),
    250                     ),
     207                    'events'   => $this->get_valid_events(),
    251208                )
    252209            ),
     
    260217
    261218    /**
     219     * Get a sample of valid events.
     220     *
     221     * @return array[]
     222     */
     223    protected function get_valid_events() {
     224        return array(
     225            array(
     226                'type'                 => 'meetup',
     227                'title'                => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
     228                'url'                  => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
     229                'meetup'               => 'The East Bay WordPress Meetup Group',
     230                'meetup_url'           => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
     231                'start_unix_timestamp' => strtotime( 'next Sunday 1pm' ),
     232                'end_unix_timestamp'   => strtotime( 'next Sunday 2pm' ),
     233
     234                'location'             => array(
     235                    'location'  => 'Oakland, CA, USA',
     236                    'country'   => 'us',
     237                    'latitude'  => 37.808453,
     238                    'longitude' => -122.26593,
     239                ),
     240            ),
     241
     242            array(
     243                'type'                 => 'meetup',
     244                'title'                => 'Part 3- Site Maintenance - Tools to Make It Easy',
     245                'url'                  => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
     246                'meetup'               => 'WordPress Bay Area Foothills Group',
     247                'meetup_url'           => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
     248                'start_unix_timestamp' => strtotime( 'next Wednesday 1:30pm' ),
     249                'end_unix_timestamp'   => strtotime( 'next Wednesday 2:30pm' ),
     250
     251                'location'             => array(
     252                    'location'  => 'Milpitas, CA, USA',
     253                    'country'   => 'us',
     254                    'latitude'  => 37.432813,
     255                    'longitude' => -121.907095,
     256                ),
     257            ),
     258
     259            array(
     260                'type'                 => 'wordcamp',
     261                'title'                => 'WordCamp San Francisco',
     262                'url'                  => 'https://sf.wordcamp.org/2020/',
     263                'meetup'               => null,
     264                'meetup_url'           => null,
     265                'start_unix_timestamp' => strtotime( 'next Saturday' ),
     266                'end_unix_timestamp'   => strtotime( 'next Saturday 8pm' ),
     267
     268                'location'             => array(
     269                    'location'  => 'San Francisco, CA',
     270                    'country'   => 'US',
     271                    'latitude'  => 37.432813,
     272                    'longitude' => -121.907095,
     273                ),
     274            ),
     275        );
     276    }
     277
     278    /**
     279     * Test: `trim_events()` should immediately remove expired events.
     280     *
     281     * @covers WP_Community_Events::trim_events
     282     *
     283     * @since 5.5.2
     284     */
     285    public function test_trim_expired_events() {
     286        $trim_events = new ReflectionMethod( $this->instance, 'trim_events' );
     287        $trim_events->setAccessible( true );
     288
     289        $events = $this->get_valid_events();
     290
     291        // This should be removed because it's already ended.
     292        $events[0]['start_unix_timestamp'] = strtotime( '1 hour ago' );
     293        $events[0]['end_unix_timestamp']   = strtotime( '2 seconds ago' );
     294
     295        // This should remain because it hasn't ended yet.
     296        $events[1]['start_unix_timestamp'] = strtotime( '2 seconds ago' );
     297        $events[1]['end_unix_timestamp']   = strtotime( '+1 hour' );
     298
     299        $actual = $trim_events->invoke( $this->instance, $events );
     300
     301        $this->assertCount( 2, $actual );
     302        $this->assertSame( $actual[0]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
     303        $this->assertSame( $actual[1]['title'], 'WordCamp San Francisco' );
     304    }
     305
     306    /**
    262307     * Test: get_events() should return the events with the WordCamp pinned in the prepared list.
    263308     *
     309     * @covers WP_Community_Events::trim_events
     310     *
    264311     * @since 4.9.7
    265      */
    266     public function test_get_events_pin_wordcamp() {
    267         add_filter( 'pre_http_request', array( $this, '_http_request_valid_response_unpinned_wordcamp' ) );
    268 
    269         $response_body = $this->instance->get_events();
     312     * @since 5.5.2 Tests `trim_events()` directly instead of indirectly via `get_events()`.
     313     */
     314    public function test_trim_events_pin_wordcamp() {
     315        $trim_events = new ReflectionMethod( $this->instance, 'trim_events' );
     316        $trim_events->setAccessible( true );
     317
     318        $actual = $trim_events->invoke( $this->instance, $this->_events_with_unpinned_wordcamp() );
    270319
    271320        /*
    272          * San Diego was at position 3 in the mock API response, but pinning puts it at position 2,
     321         * San Diego was at index 3 in the mock API response, but pinning puts it at index 2,
    273322         * so that it remains in the list. The other events should remain unchanged.
    274323         */
    275         $this->assertCount( 3, $response_body['events'] );
    276         $this->assertEquals( $response_body['events'][0]['title'], 'Flexbox + CSS Grid: Magic for Responsive Layouts' );
    277         $this->assertEquals( $response_body['events'][1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
    278         $this->assertEquals( $response_body['events'][2]['title'], 'WordCamp San Diego' );
    279 
    280         remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response_unpinned_wordcamp' ) );
    281     }
    282 
    283     /**
    284      * Simulates a valid HTTP response where a WordCamp needs to be pinned higher than it's default position.
     324        $this->assertCount( 3, $actual );
     325        $this->assertSame( $actual[0]['title'], 'Flexbox + CSS Grid: Magic for Responsive Layouts' );
     326        $this->assertSame( $actual[1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
     327        $this->assertSame( $actual[2]['title'], 'WordCamp San Diego' );
     328    }
     329
     330    /**
     331     * Simulates a scenario where a WordCamp needs to be pinned higher than it's default position.
    285332     *
    286333     * @since 4.9.7
    287      *
    288      * @return array A mock HTTP response.
    289      */
    290     public function _http_request_valid_response_unpinned_wordcamp() {
    291         return array(
    292             'headers'  => '',
    293             'response' => array( 'code' => 200 ),
    294             'cookies'  => '',
    295             'filename' => '',
    296             'body'     => wp_json_encode(
    297                 array(
    298                     'location' => $this->get_user_location(),
    299                     'events'   => array(
    300                         array(
    301                             'type'       => 'meetup',
    302                             'title'      => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
    303                             'url'        => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
    304                             'meetup'     => 'The East Bay WordPress Meetup Group',
    305                             'meetup_url' => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
    306                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Monday 1pm' ) ),
    307                             'location'   => array(
    308                                 'location'  => 'Oakland, CA, USA',
    309                                 'country'   => 'us',
    310                                 'latitude'  => 37.808453,
    311                                 'longitude' => -122.26593,
    312                             ),
    313                         ),
    314                         array(
    315                             'type'       => 'meetup',
    316                             'title'      => 'Part 3- Site Maintenance - Tools to Make It Easy',
    317                             'url'        => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
    318                             'meetup'     => 'WordPress Bay Area Foothills Group',
    319                             'meetup_url' => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
    320                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Tuesday 1:30pm' ) ),
    321                             'location'   => array(
    322                                 'location'  => 'Milpitas, CA, USA',
    323                                 'country'   => 'us',
    324                                 'latitude'  => 37.432813,
    325                                 'longitude' => -121.907095,
    326                             ),
    327                         ),
    328                         array(
    329                             'type'       => 'meetup',
    330                             'title'      => 'WordPress Q&A',
    331                             'url'        => 'https://www.meetup.com/sanjosewp/events/245419844/',
    332                             'meetup'     => 'The San Jose WordPress Meetup',
    333                             'meetup_url' => 'https://www.meetup.com/sanjosewp/',
    334                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Wednesday 5:30pm' ) ),
    335                             'location'   => array(
    336                                 'location'  => 'Milpitas, CA, USA',
    337                                 'country'   => 'us',
    338                                 'latitude'  => 37.244194,
    339                                 'longitude' => -121.889313,
    340                             ),
    341                         ),
    342                         array(
    343                             'type'       => 'wordcamp',
    344                             'title'      => 'WordCamp San Diego',
    345                             'url'        => 'https://2018.sandiego.wordcamp.org',
    346                             'meetup'     => null,
    347                             'meetup_url' => null,
    348                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Thursday 9am' ) ),
    349                             'location'   => array(
    350                                 'location'  => 'San Diego, CA',
    351                                 'country'   => 'US',
    352                                 'latitude'  => 32.7220419,
    353                                 'longitude' => -117.1534513,
    354                             ),
    355                         ),
    356                     ),
    357                 )
     334     * @since 5.5.2 Accepts and returns only the events, rather than an entire HTTP response.
     335     *
     336     * @return array A list of mock events.
     337     */
     338    public function _events_with_unpinned_wordcamp() {
     339        return array(
     340            array(
     341                'type'                 => 'meetup',
     342                'title'                => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
     343                'url'                  => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
     344                'meetup'               => 'The East Bay WordPress Meetup Group',
     345                'meetup_url'           => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
     346                'start_unix_timestamp' => strtotime( 'next Monday 1pm' ),
     347                'end_unix_timestamp'   => strtotime( 'next Monday 2pm' ),
     348
     349                'location'             => array(
     350                    'location'  => 'Oakland, CA, USA',
     351                    'country'   => 'us',
     352                    'latitude'  => 37.808453,
     353                    'longitude' => -122.26593,
     354                ),
     355            ),
     356
     357            array(
     358                'type'                 => 'meetup',
     359                'title'                => 'Part 3- Site Maintenance - Tools to Make It Easy',
     360                'url'                  => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
     361                'meetup'               => 'WordPress Bay Area Foothills Group',
     362                'meetup_url'           => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
     363                'start_unix_timestamp' => strtotime( 'next Tuesday 1:30pm' ),
     364                'end_unix_timestamp'   => strtotime( 'next Tuesday 2:30pm' ),
     365
     366                'location'             => array(
     367                    'location'  => 'Milpitas, CA, USA',
     368                    'country'   => 'us',
     369                    'latitude'  => 37.432813,
     370                    'longitude' => -121.907095,
     371                ),
     372            ),
     373
     374            array(
     375                'type'                 => 'meetup',
     376                'title'                => 'WordPress Q&A',
     377                'url'                  => 'https://www.meetup.com/sanjosewp/events/245419844/',
     378                'meetup'               => 'The San Jose WordPress Meetup',
     379                'meetup_url'           => 'https://www.meetup.com/sanjosewp/',
     380                'start_unix_timestamp' => strtotime( 'next Wednesday 5:30pm' ),
     381                'end_unix_timestamp'   => strtotime( 'next Wednesday 6:30pm' ),
     382
     383                'location'             => array(
     384                    'location'  => 'Milpitas, CA, USA',
     385                    'country'   => 'us',
     386                    'latitude'  => 37.244194,
     387                    'longitude' => -121.889313,
     388                ),
     389            ),
     390
     391            array(
     392                'type'                 => 'wordcamp',
     393                'title'                => 'WordCamp San Diego',
     394                'url'                  => 'https://2018.sandiego.wordcamp.org',
     395                'meetup'               => null,
     396                'meetup_url'           => null,
     397                'start_unix_timestamp' => strtotime( 'next Thursday 9am' ),
     398                'end_unix_timestamp'   => strtotime( 'next Thursday 10am' ),
     399
     400                'location'             => array(
     401                    'location'  => 'San Diego, CA',
     402                    'country'   => 'US',
     403                    'latitude'  => 32.7220419,
     404                    'longitude' => -117.1534513,
     405                ),
    358406            ),
    359407        );
     
    364412     * falls into the list.
    365413     *
     414     * @covers WP_Community_Events::trim_events
     415     *
    366416     * @since 4.9.7
    367      */
    368     public function test_get_events_dont_pin_multiple_wordcamps() {
    369         add_filter( 'pre_http_request', array( $this, '_http_request_valid_response_multiple_wordcamps' ) );
    370 
    371         $response_body = $this->instance->get_events();
     417     * @since 5.5.2 Tests `trim_events()` directly instead of indirectly via `get_events()`.
     418     */
     419    public function test_trim_events_dont_pin_multiple_wordcamps() {
     420        $trim_events = new ReflectionMethod( $this->instance, 'trim_events' );
     421        $trim_events->setAccessible( true );
     422
     423        $actual = $trim_events->invoke( $this->instance, $this->_events_with_multiple_wordcamps() );
    372424
    373425        /*
     
    375427         * WordCamp LA should not be stuck to the list, because San Diego already appears naturally.
    376428         */
    377         $this->assertCount( 3, $response_body['events'] );
    378         $this->assertEquals( $response_body['events'][0]['title'], 'WordCamp San Diego' );
    379         $this->assertEquals( $response_body['events'][1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
    380         $this->assertEquals( $response_body['events'][2]['title'], 'WordPress Q&A' );
    381 
    382         remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response_multiple_wordcamps' ) );
     429        $this->assertCount( 3, $actual );
     430        $this->assertSame( $actual[0]['title'], 'WordCamp San Diego' );
     431        $this->assertSame( $actual[1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
     432        $this->assertSame( $actual[2]['title'], 'WordPress Q&A' );
    383433    }
    384434
     
    388438     *
    389439     * @since 4.9.7
     440     * @since 5.5.2 Tests `trim_events()` directly instead of indirectly via `get_events()`.
    390441     *
    391442     * @return array A mock HTTP response.
    392443     */
    393     public function _http_request_valid_response_multiple_wordcamps() {
    394         return array(
    395             'headers'  => '',
    396             'response' => array( 'code' => 200 ),
    397             'cookies'  => '',
    398             'filename' => '',
    399             'body'     => wp_json_encode(
    400                 array(
    401                     'location' => $this->get_user_location(),
    402                     'events'   => array(
    403                         array(
    404                             'type'       => 'meetup',
    405                             'title'      => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
    406                             'url'        => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
    407                             'meetup'     => 'The East Bay WordPress Meetup Group',
    408                             'meetup_url' => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
    409                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( '2 days ago' ) ),
    410                             'location'   => array(
    411                                 'location'  => 'Oakland, CA, USA',
    412                                 'country'   => 'us',
    413                                 'latitude'  => 37.808453,
    414                                 'longitude' => -122.26593,
    415                             ),
    416                         ),
    417                         array(
    418                             'type'       => 'wordcamp',
    419                             'title'      => 'WordCamp San Diego',
    420                             'url'        => 'https://2018.sandiego.wordcamp.org',
    421                             'meetup'     => null,
    422                             'meetup_url' => null,
    423                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Tuesday 9am' ) ),
    424                             'location'   => array(
    425                                 'location'  => 'San Diego, CA',
    426                                 'country'   => 'US',
    427                                 'latitude'  => 32.7220419,
    428                                 'longitude' => -117.1534513,
    429                             ),
    430                         ),
    431                         array(
    432                             'type'       => 'meetup',
    433                             'title'      => 'Part 3- Site Maintenance - Tools to Make It Easy',
    434                             'url'        => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
    435                             'meetup'     => 'WordPress Bay Area Foothills Group',
    436                             'meetup_url' => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
    437                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Wednesday 1:30pm' ) ),
    438                             'location'   => array(
    439                                 'location'  => 'Milpitas, CA, USA',
    440                                 'country'   => 'us',
    441                                 'latitude'  => 37.432813,
    442                                 'longitude' => -121.907095,
    443                             ),
    444                         ),
    445                         array(
    446                             'type'       => 'meetup',
    447                             'title'      => 'WordPress Q&A',
    448                             'url'        => 'https://www.meetup.com/sanjosewp/events/245419844/',
    449                             'meetup'     => 'The San Jose WordPress Meetup',
    450                             'meetup_url' => 'https://www.meetup.com/sanjosewp/',
    451                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Thursday 5:30pm' ) ),
    452                             'location'   => array(
    453                                 'location'  => 'Milpitas, CA, USA',
    454                                 'country'   => 'us',
    455                                 'latitude'  => 37.244194,
    456                                 'longitude' => -121.889313,
    457                             ),
    458                         ),
    459                         array(
    460                             'type'       => 'wordcamp',
    461                             'title'      => 'WordCamp Los Angeles',
    462                             'url'        => 'https://2018.la.wordcamp.org',
    463                             'meetup'     => null,
    464                             'meetup_url' => null,
    465                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Friday 9am' ) ),
    466                             'location'   => array(
    467                                 'location'  => 'Los Angeles, CA',
    468                                 'country'   => 'US',
    469                                 'latitude'  => 34.050888,
    470                                 'longitude' => -118.285426,
    471                             ),
    472                         ),
    473                     ),
    474                 )
     444    public function _events_with_multiple_wordcamps() {
     445        return array(
     446            array(
     447                'type'                 => 'meetup',
     448                'title'                => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
     449                'url'                  => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
     450                'meetup'               => 'The East Bay WordPress Meetup Group',
     451                'meetup_url'           => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
     452                'start_unix_timestamp' => strtotime( '2 days ago' ) - HOUR_IN_SECONDS,
     453                'end_unix_timestamp'   => strtotime( '2 days ago' ),
     454
     455                'location'             => array(
     456                    'location'  => 'Oakland, CA, USA',
     457                    'country'   => 'us',
     458                    'latitude'  => 37.808453,
     459                    'longitude' => -122.26593,
     460                ),
     461            ),
     462
     463            array(
     464                'type'                 => 'wordcamp',
     465                'title'                => 'WordCamp San Diego',
     466                'url'                  => 'https://2018.sandiego.wordcamp.org',
     467                'meetup'               => null,
     468                'meetup_url'           => null,
     469                'start_unix_timestamp' => strtotime( 'next Tuesday 9am' ),
     470                'end_unix_timestamp'   => strtotime( 'next Tuesday 10am' ),
     471
     472                'location'             => array(
     473                    'location'  => 'San Diego, CA',
     474                    'country'   => 'US',
     475                    'latitude'  => 32.7220419,
     476                    'longitude' => -117.1534513,
     477                ),
     478            ),
     479
     480            array(
     481                'type'                 => 'meetup',
     482                'title'                => 'Part 3- Site Maintenance - Tools to Make It Easy',
     483                'url'                  => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
     484                'meetup'               => 'WordPress Bay Area Foothills Group',
     485                'meetup_url'           => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
     486                'start_unix_timestamp' => strtotime( 'next Wednesday 1:30pm' ),
     487                'end_unix_timestamp'   => strtotime( 'next Wednesday 2:30pm' ),
     488
     489                'location'             => array(
     490                    'location'  => 'Milpitas, CA, USA',
     491                    'country'   => 'us',
     492                    'latitude'  => 37.432813,
     493                    'longitude' => -121.907095,
     494                ),
     495            ),
     496
     497            array(
     498                'type'                 => 'meetup',
     499                'title'                => 'WordPress Q&A',
     500                'url'                  => 'https://www.meetup.com/sanjosewp/events/245419844/',
     501                'meetup'               => 'The San Jose WordPress Meetup',
     502                'meetup_url'           => 'https://www.meetup.com/sanjosewp/',
     503                'start_unix_timestamp' => strtotime( 'next Thursday 5:30pm' ),
     504                'end_unix_timestamp'   => strtotime( 'next Thursday 6:30pm' ),
     505
     506                'location'             => array(
     507                    'location'  => 'Milpitas, CA, USA',
     508                    'country'   => 'us',
     509                    'latitude'  => 37.244194,
     510                    'longitude' => -121.889313,
     511                ),
     512            ),
     513
     514            array(
     515                'type'                 => 'wordcamp',
     516                'title'                => 'WordCamp Los Angeles',
     517                'url'                  => 'https://2018.la.wordcamp.org',
     518                'meetup'               => null,
     519                'meetup_url'           => null,
     520                'start_unix_timestamp' => strtotime( 'next Friday 9am' ),
     521                'end_unix_timestamp'   => strtotime( 'next Friday 10am' ),
     522
     523                'location'             => array(
     524                    'location'  => 'Los Angeles, CA',
     525                    'country'   => 'US',
     526                    'latitude'  => 34.050888,
     527                    'longitude' => -118.285426,
     528                ),
    475529            ),
    476530        );
  • branches/5.5/tests/qunit/index.html

    r48177 r49275  
    8484
    8585        <!-- Tested files -->
     86        <script src="../../build/wp-admin/js/dashboard.js"></script>
    8687        <script src="../../build/wp-admin/js/password-strength-meter.js"></script>
     88        <script src="../../build/wp-admin/js/postbox.js"></script>
     89        <script src="../../build/wp-includes/js/dist/vendor/moment.js"></script>
     90        <script src="../../build/wp-includes/js/dist/date.js"></script>
     91        <script src="../../build/wp-includes/js/dist/i18n.js"></script>
    8792        <script src="../../build/wp-includes/js/customize-base.js"></script>
    8893        <script src="../../build/wp-includes/js/customize-models.js"></script>
     
    142147        <script src="wp-admin/js/customize-base.js"></script>
    143148        <script src="wp-admin/js/customize-header.js"></script>
     149        <script src="wp-admin/js/dashboard.js"></script>
    144150        <script src="wp-includes/js/shortcode.js"></script>
    145151        <script src="wp-includes/js/api-request.js"></script>
Note: See TracChangeset for help on using the changeset viewer.