diff --git a/CHANGELOG.md b/CHANGELOG.md index f95e2873a6..b1c0940fa3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.23.0](https://github.com/Parsely/wp-parsely/compare/3.22.1...3.23.0) - 2026-04-06 + +### Added + +- Add `wp_parsely_tracker_url` filter ([#4108](https://github.com/Parsely/wp-parsely/pull/4108)) + +### Changed + +- Update post list stats column to use icons ([#4136](https://github.com/Parsely/wp-parsely/pull/4136)) + +### Dependency Updates + +- The list of all dependency updates for this release is available [here](https://github.com/Parsely/wp-parsely/pulls?q=is%3Apr+is%3Amerged+milestone%3A3.23.0+label%3ADeps). + ## [3.22.1](https://github.com/Parsely/wp-parsely/compare/3.22.0...3.22.1) - 2026-03-30 ### Fixed diff --git a/README.md b/README.md index e33776f989..23f3a05ff5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Parse.ly -Stable tag: 3.22.1 +Stable tag: 3.23.0 Requires at least: 6.0 Tested up to: 6.9 Requires PHP: 7.4 diff --git a/build/content-helper/post-list-stats-rtl.css b/build/content-helper/post-list-stats-rtl.css index f253a4177c..1c41517e26 100644 --- a/build/content-helper/post-list-stats-rtl.css +++ b/build/content-helper/post-list-stats-rtl.css @@ -1 +1 @@ -.column-parsely-stats{width:200px}@media only screen and (max-width:991px){.column-parsely-stats{width:150px}}.column-parsely-stats .parsely-post-stats{color:#959da5;line-height:18px;min-height:54px}.column-parsely-stats .parsely-post-stats-placeholder{letter-spacing:2px}.column-parsely-stats .parsely-post-page-views{color:#000} +.column-parsely-stats .parsely-post-stats{cursor:default;display:flex;flex-wrap:wrap;gap:2px 8px;min-height:54px}.column-parsely-stats .parsely-post-stats-placeholder{color:#959da5;letter-spacing:2px}.column-parsely-stats .parsely-post-avg-time,.column-parsely-stats .parsely-post-page-views,.column-parsely-stats .parsely-post-visitors{align-items:center;display:flex;gap:4px}.column-parsely-stats .parsely-post-avg-time .dashicons,.column-parsely-stats .parsely-post-page-views .dashicons,.column-parsely-stats .parsely-post-visitors .dashicons{font-size:16px;height:16px;width:16px} diff --git a/build/content-helper/post-list-stats.asset.php b/build/content-helper/post-list-stats.asset.php index 3d000ba2a7..4ba116213e 100644 --- a/build/content-helper/post-list-stats.asset.php +++ b/build/content-helper/post-list-stats.asset.php @@ -1 +1 @@ - array(), 'version' => '150ace49707b05c46bdb'); + array('wp-i18n'), 'version' => '0f380989aa4951c0833b'); diff --git a/build/content-helper/post-list-stats.css b/build/content-helper/post-list-stats.css index f253a4177c..1c41517e26 100644 --- a/build/content-helper/post-list-stats.css +++ b/build/content-helper/post-list-stats.css @@ -1 +1 @@ -.column-parsely-stats{width:200px}@media only screen and (max-width:991px){.column-parsely-stats{width:150px}}.column-parsely-stats .parsely-post-stats{color:#959da5;line-height:18px;min-height:54px}.column-parsely-stats .parsely-post-stats-placeholder{letter-spacing:2px}.column-parsely-stats .parsely-post-page-views{color:#000} +.column-parsely-stats .parsely-post-stats{cursor:default;display:flex;flex-wrap:wrap;gap:2px 8px;min-height:54px}.column-parsely-stats .parsely-post-stats-placeholder{color:#959da5;letter-spacing:2px}.column-parsely-stats .parsely-post-avg-time,.column-parsely-stats .parsely-post-page-views,.column-parsely-stats .parsely-post-visitors{align-items:center;display:flex;gap:4px}.column-parsely-stats .parsely-post-avg-time .dashicons,.column-parsely-stats .parsely-post-page-views .dashicons,.column-parsely-stats .parsely-post-visitors .dashicons{font-size:16px;height:16px;width:16px} diff --git a/build/content-helper/post-list-stats.js b/build/content-helper/post-list-stats.js index 535ac41408..5936b41bfe 100644 --- a/build/content-helper/post-list-stats.js +++ b/build/content-helper/post-list-stats.js @@ -1 +1,4 @@ -!function(){"use strict";!function(){function s(){return document.querySelectorAll(".parsely-post-stats")}document.addEventListener("DOMContentLoaded",(function(){!function(){if(null===(n=s())||void 0===n||n.forEach((function(s){s.innerHTML="—"})),window.wpParselyPostsStatsResponse){var n,e,t,r,a=JSON.parse(window.wpParselyPostsStatsResponse);if(null==a?void 0:a.error)return e=a.error,void(null!==(r=document.querySelector(".wp-header-end"))&&(r.innerHTML+=(void 0===(t=e.htmlMessage)&&(t=""),'
'.concat(t,"
"))));(null==a?void 0:a.data)&&function(n){var e;n&&(null===(e=s())||void 0===e||e.forEach((function(s){var e=s.getAttribute("data-stats-key");if(null!==e&&void 0!==n[e]){var t=n[e];s.innerHTML="",t.page_views&&(s.innerHTML+=''.concat(t.page_views,"
")),t.visitors&&(s.innerHTML+=''.concat(t.visitors,"
")),t.avg_time&&(s.innerHTML+=''.concat(t.avg_time,"
"))}})))}(a.data)}}()}))}()}(); \ No newline at end of file +!function(){"use strict";!function(){var s=window.wp.i18n;function e(s,e,n,i){return'')+'')+''.concat(n,"")+'")+""}function n(){return document.querySelectorAll(".parsely-post-stats")}document.addEventListener("DOMContentLoaded",(function(){!function(){if(null===(i=n())||void 0===i||i.forEach((function(s){s.innerHTML="—"})),window.wpParselyPostsStatsResponse){var i,t,a,r,o=JSON.parse(window.wpParselyPostsStatsResponse);if(null==o?void 0:o.error)return t=o.error,void(null!==(r=document.querySelector(".wp-header-end"))&&(r.innerHTML+=(void 0===(a=t.htmlMessage)&&(a=""),'
'.concat(a,"
"))));(null==o?void 0:o.data)&&function(i){var t;i&&(null===(t=n())||void 0===t||t.forEach((function(n){var t=n.getAttribute("data-stats-key");if(null!==t&&void 0!==i[t]){var a=i[t];n.innerHTML="",a.page_views&&(n.innerHTML+=e("parsely-post-page-views","visibility",/* translators: %s: number of page views */ /* translators: %s: number of page views */ +(0,s.sprintf)((0,s.__)("Page views: %s","wp-parsely"),a.page_views),a.page_views)),a.visitors&&(n.innerHTML+=e("parsely-post-visitors","groups",/* translators: %s: number of visitors */ /* translators: %s: number of visitors */ +(0,s.sprintf)((0,s.__)("Visitors: %s","wp-parsely"),a.visitors),a.visitors)),a.avg_time&&(n.innerHTML+=e("parsely-post-avg-time","clock",/* translators: %s: average time spent on post */ /* translators: %s: average time spent on post */ +(0,s.sprintf)((0,s.__)("Avg. time: %s","wp-parsely"),a.avg_time),a.avg_time))}})))}(o.data)}}()}))}()}(); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 6cf3a1e153..f03bc3f1c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wp-parsely", - "version": "3.22.1", + "version": "3.23.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wp-parsely", - "version": "3.22.1", + "version": "3.23.0", "license": "GPL-2.0-or-later", "dependencies": { "@types/js-cookie": "^3.0.6", @@ -20627,16 +20627,16 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "dev": true, "license": "MIT" }, "node_modules/lodash-es": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", - "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", "dev": true, "license": "MIT" }, @@ -21495,9 +21495,9 @@ } }, "node_modules/node-forge": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", - "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", + "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", "dev": true, "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { diff --git a/package.json b/package.json index 823bf22d06..1a0ff036c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wp-parsely", - "version": "3.22.1", + "version": "3.23.0", "private": true, "description": "The Parse.ly plugin facilitates real-time and historical analytics to your content through a platform designed and built for digital publishing.", "author": "parsely, hbbtstar, jblz, mikeyarce, GaryJ, parsely_mike, acicovic, mehmoodak, vaurdan", @@ -94,7 +94,7 @@ "express": "^4.22.0", "glob": "^10.5.0", "js-yaml@^3": "3.14.2", - "node-forge": "^1.3.2", + "node-forge": "^1.4.0", "puppeteer-core": "^23.1.0", "qs": "^6.14.1" }, diff --git a/src/Utils/class-utils.php b/src/Utils/class-utils.php index 625337c9af..faeaba24e5 100644 --- a/src/Utils/class-utils.php +++ b/src/Utils/class-utils.php @@ -280,7 +280,7 @@ public static function get_formatted_time( $seconds ): string { return esc_html( sprintf( /* translators: 1: Number of seconds */ - __( '%1$d sec.', 'wp-parsely' ), + __( '%1$ds', 'wp-parsely' ), round( $seconds ) ) ); diff --git a/src/class-parsely.php b/src/class-parsely.php index 239cd18ab3..8d617b079a 100644 --- a/src/class-parsely.php +++ b/src/class-parsely.php @@ -373,8 +373,19 @@ public function get_rest_api_controller(): REST_API_Controller { public function get_tracker_url(): string { if ( $this->site_id_is_set() ) { $tracker_url = 'https://cdn.parsely.com/keys/' . $this->get_site_id() . '/p.js'; - return esc_url( $tracker_url ); + + /** + * Filters the URL of the Parse.ly tracker script. + * + * The filtered value gets sanitized with {@see esc_url_raw()}. + * + * @since 3.23.0 + * + * @param string $tracker_url The URL of the tracker script. + */ + return esc_url_raw( apply_filters( 'wp_parsely_tracker_url', $tracker_url ) ); } + return ''; } diff --git a/src/content-helper/post-list-stats/class-post-list-stats.php b/src/content-helper/post-list-stats/class-post-list-stats.php index 9ea12d9a47..62808ee69e 100644 --- a/src/content-helper/post-list-stats/class-post-list-stats.php +++ b/src/content-helper/post-list-stats/class-post-list-stats.php @@ -162,7 +162,7 @@ public function enqueue_parsely_stats_styles(): void { wp_enqueue_style( static::get_style_id(), $built_assets_url . 'post-list-stats.css', - $admin_settings_asset['dependencies'], + array(), $admin_settings_asset['version'] ); } @@ -177,7 +177,7 @@ public function enqueue_parsely_stats_styles(): void { */ public function add_parsely_stats_column_on_list_view( array $columns ): array { if ( $this->is_tracked_as_post_type() ) { - $columns['parsely-stats'] = __( 'Parse.ly Stats (7d)', 'wp-parsely' ); + $columns['parsely-stats'] = __( 'Parse.ly (7d)', 'wp-parsely' ); } return $columns; @@ -210,7 +210,7 @@ public function update_published_times_and_show_placeholder( string $column_name $stats_key = $this->get_unique_stats_key_of_current_post(); ?>
- ... +
Utils::get_formatted_number( (string) $views ) . ' ' . _n( 'page view', 'page views', $views, 'wp-parsely' ), - 'visitors' => Utils::get_formatted_number( (string) $visitors ) . ' ' . _n( 'visitor', 'visitors', $visitors, 'wp-parsely' ), - 'avg_time' => Utils::get_formatted_time( $engaged_seconds ) . ' ' . __( 'avg time', 'wp-parsely' ), + 'page_views' => Utils::get_formatted_number( (string) $views ), + 'visitors' => Utils::get_formatted_number( (string) $visitors ), + 'avg_time' => Utils::get_formatted_time( $engaged_seconds ), ); $parsely_stats_map[ $key ] = $stats; diff --git a/src/content-helper/post-list-stats/post-list-stats.scss b/src/content-helper/post-list-stats/post-list-stats.scss index 2fb0480f88..9c6c9c6259 100644 --- a/src/content-helper/post-list-stats/post-list-stats.scss +++ b/src/content-helper/post-list-stats/post-list-stats.scss @@ -1,21 +1,28 @@ .column-parsely-stats { - width: 200px; - - @media only screen and (max-width: 991px) { - width: 150px; - } - .parsely-post-stats { - color: #959da5; + cursor: default; + display: flex; + flex-wrap: wrap; + gap: 2px 8px; min-height: 54px; - line-height: 18px; } .parsely-post-stats-placeholder { + color: #959da5; letter-spacing: 2px; } - .parsely-post-page-views { - color: #000; + .parsely-post-page-views, + .parsely-post-visitors, + .parsely-post-avg-time { + display: flex; + align-items: center; + gap: 4px; + + .dashicons { + font-size: 16px; + width: 16px; + height: 16px; + } } } diff --git a/src/content-helper/post-list-stats/post-list-stats.ts b/src/content-helper/post-list-stats/post-list-stats.ts index e05e9541c9..17e46e227c 100644 --- a/src/content-helper/post-list-stats/post-list-stats.ts +++ b/src/content-helper/post-list-stats/post-list-stats.ts @@ -1,3 +1,4 @@ +import { __, sprintf } from '@wordpress/i18n'; import { ParselyAPIError, ParselyAPIErrorInfo } from './common.interface'; export interface ParselyPostsStatsResponse extends ParselyAPIError { @@ -71,19 +72,50 @@ function showParselyStats( parselyStatsMap: ParselyStatsMap ): void { statsElement.innerHTML = ''; if ( stats.page_views ) { - statsElement.innerHTML += `${ stats.page_views }
`; + statsElement.innerHTML += getStatSpan( + 'parsely-post-page-views', 'visibility', + /* translators: %s: number of page views */ + sprintf( __( 'Page views: %s', 'wp-parsely' ), stats.page_views ), + stats.page_views + ); } if ( stats.visitors ) { - statsElement.innerHTML += `${ stats.visitors }
`; + statsElement.innerHTML += getStatSpan( + 'parsely-post-visitors', 'groups', + /* translators: %s: number of visitors */ + sprintf( __( 'Visitors: %s', 'wp-parsely' ), stats.visitors ), + stats.visitors + ); } if ( stats.avg_time ) { - statsElement.innerHTML += `${ stats.avg_time }
`; + statsElement.innerHTML += getStatSpan( + 'parsely-post-avg-time', 'clock', + /* translators: %s: average time spent on post */ + sprintf( __( 'Avg. time: %s', 'wp-parsely' ), stats.avg_time ), + stats.avg_time + ); } } ); } +/** + * Gets HTML for a single stat metric span with an icon and screen-reader label. + * + * @param {string} className CSS class for the outer span. + * @param {string} dashicon Dashicon class name (without `dashicons` prefix). + * @param {string} srText Full screen reader text (including the value). + * @param {string} value The metric value to display visually. + */ +function getStatSpan( className: string, dashicon: string, srText: string, value: string ): string { + return `` + + `` + + `${ srText }` + + `` + + ``; +} + /** * Shows Parse.ly Stats error as a wp-admin error notice. * diff --git a/tests/Integration/ContentHelper/ContentHelperPostListStatsTest.php b/tests/Integration/ContentHelper/ContentHelperPostListStatsTest.php index 7ce13efc8a..29a497df34 100644 --- a/tests/Integration/ContentHelper/ContentHelperPostListStatsTest.php +++ b/tests/Integration/ContentHelper/ContentHelperPostListStatsTest.php @@ -41,7 +41,7 @@ final class ContentHelperPostListStatsTest extends ContentHelperFeatureTest { * * @var string */ - private static $parsely_stats_column_header = 'Parse.ly Stats (7d)'; + private static $parsely_stats_column_header = 'Parse.ly (7d)'; /** * Internal variable. @@ -604,7 +604,7 @@ private function show_content_on_parsely_stats_column( array $posts, string $pos * @return string */ private function get_parsely_stats_placeholder_content( string $key ): string { - return "
\n ...\n
\n "; + return "
\n \n
\n "; } /** @@ -1118,6 +1118,22 @@ public function test_parsely_stats_response_on_valid_post_type_and_having_data_f 'avg_engaged' => 0.01, ), ), + array( + 'url' => 'http://example.com/2010/01/14/title-14-publish', + 'metrics' => array( + 'views' => 1, + 'visitors' => 1, + 'avg_engaged' => 1.0, // Exactly 60 seconds: s -> m:ss boundary. + ), + ), + array( + 'url' => 'http://example.com/2010/01/15/title-15-publish', + 'metrics' => array( + 'views' => 1, + 'visitors' => 1, + 'avg_engaged' => 60.0, // Exactly 3600 seconds: m:ss -> h:mm:ss boundary. + ), + ), ); $res = $this->get_parsely_stats_response( $posts, @@ -1134,64 +1150,74 @@ public function test_parsely_stats_response_on_valid_post_type_and_having_data_f self::assertSame( array( '/2010/01/01/title-1-publish' => array( - 'page_views' => '0 page views', - 'visitors' => '0 visitors', - 'avg_time' => '0 sec. avg time', + 'page_views' => '0', + 'visitors' => '0', + 'avg_time' => '0s', // 0 seconds. ), '/2010/01/02/title-2-publish' => array( - 'page_views' => '1 page view', - 'visitors' => '1 visitor', - 'avg_time' => '0 sec. avg time', // 0.3 seconds. + 'page_views' => '1', + 'visitors' => '1', + 'avg_time' => '0s', // 0.3 seconds. ), '/2010/01/03/title-3-publish' => array( - 'page_views' => '1 page view', - 'visitors' => '1 visitor', - 'avg_time' => '1 sec. avg time', // 0.6 seconds. + 'page_views' => '1', + 'visitors' => '1', + 'avg_time' => '1s', // 0.6 seconds. ), '/2010/01/04/title-4-publish' => array( - 'page_views' => '1 page view', - 'visitors' => '1 visitor', - 'avg_time' => '59 sec. avg time', // 59 seconds. + 'page_views' => '1', + 'visitors' => '1', + 'avg_time' => '59s', // 59 seconds. ), '/2010/01/05/title-5-publish' => array( - 'page_views' => '1.1k page views', - 'visitors' => '1.1M visitors', - 'avg_time' => '1:00 avg time', // 59.52 seconds. + 'page_views' => '1.1k', + 'visitors' => '1.1M', + 'avg_time' => '1:00', // 59.52 seconds. ), '/2010/01/06/title-6-publish' => array( - 'page_views' => '1.1k page views', - 'visitors' => '1.1M visitors', - 'avg_time' => '1:00 avg time', // 59.7 seconds. + 'page_views' => '1.1k', + 'visitors' => '1.1M', + 'avg_time' => '1:00', // 59.7 seconds. ), '/2010/01/07/title-7-publish' => array( - 'page_views' => '1 page view', - 'visitors' => '1 visitor', - 'avg_time' => '1:05 avg time', // 65 seconds. + 'page_views' => '1', + 'visitors' => '1', + 'avg_time' => '1:05', // 65 seconds. ), '/2010/01/08/title-8-publish' => array( - 'page_views' => '1.1k page views', - 'visitors' => '1.1M visitors', - 'avg_time' => '1:06 avg time', // 66 seconds. + 'page_views' => '1.1k', + 'visitors' => '1.1M', + 'avg_time' => '1:06', // 66 seconds. ), '/2010/01/09/title-9-publish' => array( - 'page_views' => '1.1k page views', - 'visitors' => '1.1M visitors', - 'avg_time' => '1:01:05 avg time', // 3665 seconds. + 'page_views' => '1.1k', + 'visitors' => '1.1M', + 'avg_time' => '1:01:05', // 3665 seconds. ), '/2010/01/11/title-11-publish' => array( - 'page_views' => '1 page view', - 'visitors' => '0 visitors', - 'avg_time' => '0 sec. avg time', + 'page_views' => '1', + 'visitors' => '0', + 'avg_time' => '0s', ), '/2010/01/12/title-12-publish' => array( - 'page_views' => '0 page views', - 'visitors' => '1 visitor', - 'avg_time' => '0 sec. avg time', + 'page_views' => '0', + 'visitors' => '1', + 'avg_time' => '0s', ), '/2010/01/13/title-13-publish' => array( - 'page_views' => '0 page views', - 'visitors' => '0 visitors', - 'avg_time' => '1 sec. avg time', // 0.6 seconds. + 'page_views' => '0', + 'visitors' => '0', + 'avg_time' => '1s', // 0.6 seconds. + ), + '/2010/01/14/title-14-publish' => array( + 'page_views' => '1', + 'visitors' => '1', + 'avg_time' => '1:00', // Exactly 60 seconds: s -> m:ss boundary. + ), + '/2010/01/15/title-15-publish' => array( + 'page_views' => '1', + 'visitors' => '1', + 'avg_time' => '1:00:00', // Exactly 3600 seconds: m:ss -> h:mm:ss boundary. ), ), $res['data'] ?? null @@ -1238,9 +1264,9 @@ public function test_parsely_stats_response_on_valid_hierarchal_post_type_and_ha self::assertSame( array( '/2010/01/01/title-1-publish' => array( - 'page_views' => '1.1k page views', - 'visitors' => '1.1M visitors', - 'avg_time' => '1:06 avg time', + 'page_views' => '1.1k', + 'visitors' => '1.1M', + 'avg_time' => '1:06', ), ), $res['data'] ?? null diff --git a/tests/Integration/OtherTest.php b/tests/Integration/OtherTest.php index b2f63ba764..575478e903 100644 --- a/tests/Integration/OtherTest.php +++ b/tests/Integration/OtherTest.php @@ -401,4 +401,29 @@ public function test_get_tracker_no_site_id(): void { $expected = ''; self::assertSame( $expected, self::$parsely->get_tracker_url() ); } + + /** + * Verifies that the tracker URL can be overridden via the + * wp_parsely_tracker_url filter. + * + * @since 3.23.0 + * + * @covers \Parsely\Parsely::get_tracker_url + * @uses \Parsely\Parsely::site_id_is_set + * @uses \Parsely\Parsely::get_site_id + * @uses \Parsely\Parsely::get_options + */ + public function test_get_tracker_url_filter(): void { + self::set_options( array( 'apikey' => self::VALID_SITE_ID ) ); + $custom_url = 'https://my-first-party-cdn.example.com/p.js'; + + add_filter( + 'wp_parsely_tracker_url', + function () use ( $custom_url ): string { + return $custom_url; + } + ); + + self::assertSame( $custom_url, self::$parsely->get_tracker_url() ); + } } diff --git a/tests/Unit/Utils/UtilsTest.php b/tests/Unit/Utils/UtilsTest.php index fbf67132d6..252a7c51cb 100644 --- a/tests/Unit/Utils/UtilsTest.php +++ b/tests/Unit/Utils/UtilsTest.php @@ -159,27 +159,27 @@ public function test_get_formatted_time(): void { $tests_data = array( array( 'args' => array( 'seconds' => 0 ), - 'expected_output' => '0 sec.', + 'expected_output' => '0s', 'msg' => 'Should show seconds.', ), array( 'args' => array( 'seconds' => 0.5 ), - 'expected_output' => '1 sec.', + 'expected_output' => '1s', 'msg' => 'Should show seconds.', ), array( 'args' => array( 'seconds' => 0.5000 ), - 'expected_output' => '1 sec.', + 'expected_output' => '1s', 'msg' => 'Should show seconds.', ), array( 'args' => array( 'seconds' => 0.51 ), - 'expected_output' => '1 sec.', + 'expected_output' => '1s', 'msg' => 'Should show seconds.', ), array( 'args' => array( 'seconds' => 59 ), - 'expected_output' => '59 sec.', + 'expected_output' => '59s', 'msg' => 'Should show seconds.', ), array( diff --git a/tests/e2e/utils.ts b/tests/e2e/utils.ts index 66320221f9..282829219c 100644 --- a/tests/e2e/utils.ts +++ b/tests/e2e/utils.ts @@ -8,7 +8,7 @@ import { type Page } from '@playwright/test'; */ import { Admin } from '@wordpress/e2e-test-utils-playwright'; -export const PLUGIN_VERSION = '3.22.1'; +export const PLUGIN_VERSION = '3.23.0'; export const VALID_SITE_ID = 'demoaccount.parsely.com'; export const INVALID_SITE_ID = 'invalid.parsely.com'; export const VALID_API_SECRET = 'valid_api_secret'; diff --git a/tests/js/content-helper/post-list-stats.test.tsx b/tests/js/content-helper/post-list-stats.test.tsx index 2ed22d821b..08cbdecb9b 100644 --- a/tests/js/content-helper/post-list-stats.test.tsx +++ b/tests/js/content-helper/post-list-stats.test.tsx @@ -22,11 +22,11 @@ describe( 'src/content-helper/post-list-stats', () => { window.wpParselyPostsStatsResponse = JSON.stringify( { data: { - 'key-1': { page_views: '0 page views', visitors: '0 visitors', avg_time: '0 sec. avg time' }, - 'key-3': { page_views: '3 page views', visitors: '3 visitors', avg_time: '3 sec. avg time' }, - 'key-4': { page_views: '4 page views' }, - 'key-5': { visitors: '5 visitors' }, - 'key-6': { avg_time: '6 sec. avg time' }, + 'key-1': { page_views: '0', visitors: '0', avg_time: '0s' }, + 'key-3': { page_views: '3', visitors: '3', avg_time: '3s' }, + 'key-4': { page_views: '4' }, + 'key-5': { visitors: '5' }, + 'key-6': { avg_time: '6s' }, }, error: null, } ); @@ -40,32 +40,32 @@ describe( 'src/content-helper/post-list-stats', () => { expect( allPostStats.length ).toBe( 7 ); const postStat1 = getPostStatsElement( 'key-1' ); - expect( getPageViewsElement( postStat1 )?.textContent ).toBe( '0 page views' ); - expect( getVisitorsElement( postStat1 )?.textContent ).toBe( '0 visitors' ); - expect( getAvgTimeElement( postStat1 )?.textContent ).toBe( '0 sec. avg time' ); + expect( getPageViewsElement( postStat1 )?.textContent ).toBe( 'Page views: 0' ); + expect( getVisitorsElement( postStat1 )?.textContent ).toBe( 'Visitors: 0' ); + expect( getAvgTimeElement( postStat1 )?.textContent ).toBe( 'Avg. time: 0s' ); const postStat2 = getPostStatsElement( 'key-2' ); expect( postStat2?.textContent ).toBe( '—' ); const postStat3 = getPostStatsElement( 'key-3' ); - expect( getPageViewsElement( postStat3 )?.textContent ).toBe( '3 page views' ); - expect( getVisitorsElement( postStat3 )?.textContent ).toBe( '3 visitors' ); - expect( getAvgTimeElement( postStat3 )?.textContent ).toBe( '3 sec. avg time' ); + expect( getPageViewsElement( postStat3 )?.textContent ).toBe( 'Page views: 3' ); + expect( getVisitorsElement( postStat3 )?.textContent ).toBe( 'Visitors: 3' ); + expect( getAvgTimeElement( postStat3 )?.textContent ).toBe( 'Avg. time: 3s' ); const postStat4 = getPostStatsElement( 'key-4' ); - expect( getPageViewsElement( postStat4 )?.textContent ).toBe( '4 page views' ); + expect( getPageViewsElement( postStat4 )?.textContent ).toBe( 'Page views: 4' ); expect( getVisitorsElement( postStat4 ) ).toBeNull(); expect( getAvgTimeElement( postStat4 ) ).toBeNull(); const postStat5 = getPostStatsElement( 'key-5' ); expect( getPageViewsElement( postStat5 ) ).toBeNull(); - expect( getVisitorsElement( postStat5 )?.textContent ).toBe( '5 visitors' ); + expect( getVisitorsElement( postStat5 )?.textContent ).toBe( 'Visitors: 5' ); expect( getAvgTimeElement( postStat5 ) ).toBeNull(); const postStat6 = getPostStatsElement( 'key-6' ); expect( getPageViewsElement( postStat6 ) ).toBeNull(); expect( getVisitorsElement( postStat6 ) ).toBeNull(); - expect( getAvgTimeElement( postStat6 )?.textContent ).toBe( '6 sec. avg time' ); + expect( getAvgTimeElement( postStat6 )?.textContent ).toBe( 'Avg. time: 6s' ); const postStat7 = getPostStatsElement( 'key-7' ); expect( postStat7?.textContent ).toBe( '—' ); @@ -123,7 +123,7 @@ function getParselyStatsPlaceholders( numOfPlaceholders: number ): React.JSX.Ele placeholders.push( // This placeholder content should be kept in sync with Post_List_Stats
- ... +
); } @@ -144,15 +144,15 @@ function getPostStatsElement( key: string ): Element | null { } function getPageViewsElement( postStatElement: Element | null ): Element | null { - return postStatElement ? postStatElement.querySelector( `.parsely-post-page-views` ) : null; + return postStatElement ? postStatElement.querySelector( '.parsely-post-page-views .screen-reader-text' ) : null; } function getVisitorsElement( postStatElement: Element | null ): Element | null { - return postStatElement ? postStatElement.querySelector( `.parsely-post-visitors` ) : null; + return postStatElement ? postStatElement.querySelector( '.parsely-post-visitors .screen-reader-text' ) : null; } function getAvgTimeElement( postStatElement: Element | null ): Element | null { - return postStatElement ? postStatElement.querySelector( `.parsely-post-avg-time` ) : null; + return postStatElement ? postStatElement.querySelector( '.parsely-post-avg-time .screen-reader-text' ) : null; } function getStatsErrorElement(): Element | null { diff --git a/wp-parsely.php b/wp-parsely.php index 59dbc003e4..28c368b689 100644 --- a/wp-parsely.php +++ b/wp-parsely.php @@ -11,7 +11,7 @@ * Plugin Name: Parse.ly * Plugin URI: https://docs.parse.ly/wordpress * Description: This plugin makes it a snap to add Parse.ly tracking code and metadata to your WordPress blog. - * Version: 3.22.1 + * Version: 3.23.0 * Author: Parse.ly * Author URI: https://www.parse.ly * Text Domain: wp-parsely @@ -50,7 +50,7 @@ return; } -const PARSELY_VERSION = '3.22.1'; +const PARSELY_VERSION = '3.23.0'; const PARSELY_FILE = __FILE__; const PARSELY_DATA_SCHEMA_VERSION = '1'; const PARSELY_CACHE_GROUP = 'wp-parsely';