diff --git a/components/test-run-alerts/_style.scss b/components/test-run-alerts/_style.scss
index 72eaf45..f9356fe 100644
--- a/components/test-run-alerts/_style.scss
+++ b/components/test-run-alerts/_style.scss
@@ -30,7 +30,7 @@
padding: 0 20px;
position: sticky;
top: -0.1px;
- z-index: 1;
+ z-index: 3;
}
&-link {
diff --git a/includes/core/utilities/class-image-helpers.php b/includes/core/utilities/class-image-helpers.php
index 38df4dc..1407bab 100644
--- a/includes/core/utilities/class-image-helpers.php
+++ b/includes/core/utilities/class-image-helpers.php
@@ -45,7 +45,7 @@ public static function alert_image_aspect_ratio( $alert ) {
* @return string
*/
public static function get_screenshot_url( $object, $type, $size = 'full' ) {
- $property = "${type}_screenshot_url";
+ $property = "{$type}_screenshot_url";
if ( ! property_exists( $object, $property ) ) {
return '';
diff --git a/includes/features/class-onboarding.php b/includes/features/class-onboarding.php
index ba8a7bc..d63759e 100644
--- a/includes/features/class-onboarding.php
+++ b/includes/features/class-onboarding.php
@@ -112,7 +112,7 @@ public function get_onboardings() {
'description' => wp_kses_post( __( 'Starting from tomorrow, your Test will run daily, ensuring consistent monitoring of your page.', 'visual-regression-tests' ) ),
],
[
- 'element' => '.vrts_navigation_item a[href$="admin.php?page=vrts-settings"]',
+ 'element' => '.vrts-admin-header__navigation-link[href$="admin.php?page=vrts-settings"]',
'title' => wp_kses_post( __( '🛠️ Fine-tune your setup', 'visual-regression-tests' ) ),
'description' => wp_kses_post( __( 'Further customize your Test configuration and plugin settings for an optimized experience.', 'visual-regression-tests' ) ),
],
@@ -137,7 +137,7 @@ public function get_onboardings() {
[
'side' => 'bottom',
'align' => 'center',
- 'element' => '.vrts_navigation_item a[href$="admin.php?page=vrts-runs"]',
+ 'element' => '.vrts-admin-header__navigation-link[href$="admin.php?page=vrts-runs"]',
'title' => wp_kses_post( __( '🚀 Meet the new Runs!', 'visual-regression-tests' ) ),
'description' => wp_kses_post( __( 'Alerts are now bundled into Runs. Get a single report for each daily test, manual test, API trigger, or new: WordPress & plugin update (Pro)!', 'visual-regression-tests' ) ),
],
diff --git a/includes/list-tables/class-test-runs-list-table.php b/includes/list-tables/class-test-runs-list-table.php
index 31e1dbb..e53bc27 100644
--- a/includes/list-tables/class-test-runs-list-table.php
+++ b/includes/list-tables/class-test-runs-list-table.php
@@ -160,14 +160,6 @@ public function prepare_items() {
];
$this->items = Test_Run::get_items( $args );
- $test_run_ids = wp_list_pluck( $this->items, 'id' );
- $alert_counts = [];
- foreach ( Alert::get_unread_count_by_test_run_ids( $test_run_ids ) as $alert_count ) {
- $alert_counts[ $alert_count->test_run_id ] = $alert_count->count;
- }
- foreach ( $this->items as $item ) {
- $item->alerts_count = $alert_counts[ $item->id ] ?? 0;
- }
$total_items = 0;
if ( null !== $args['filter_status'] ) {
@@ -198,7 +190,7 @@ public function single_row( $item ) {
class=""
data-test-run-id="id ); ?>"
data-test-run-new=""
- alerts_count > 0 ? 'data-has-alerts' : ''; ?>
+ unread_alerts_count > 0 ? 'data-has-alerts' : ''; ?>
>
single_row_columns( $item ); ?>
@@ -324,11 +316,10 @@ public function column_trigger( $item ) {
* @return string
*/
public function column_status( $item ) {
- $alerts_count = count( maybe_unserialize( $item->alerts ) ?? [] );
$tests_count = count( maybe_unserialize( $item->tests ) ?? [] );
- if ( $alerts_count > 0 ) {
+ if ( $item->alerts_count > 0 ) {
$status_class = 'paused';
- $status_text = esc_html__( 'Changes detected ', 'visual-regression-tests' ) . sprintf( '(%s)', $alerts_count );
+ $status_text = esc_html__( 'Changes detected ', 'visual-regression-tests' ) . sprintf( '(%s)', $item->alerts_count );
} else {
$status_class = 'running';
diff --git a/includes/models/class-test-run.php b/includes/models/class-test-run.php
index cb40afb..1899177 100644
--- a/includes/models/class-test-run.php
+++ b/includes/models/class-test-run.php
@@ -42,7 +42,7 @@ public static function get_items( $args = [], $return_count = false ) {
if ( isset( $args['filter_status'] ) && null !== $args['filter_status'] ) {
if ( 'changes-detected' === $args['filter_status'] ) {
- $where .= ' AND alerts IS NOT NULL';
+ $where .= ' AND alerts_count > 0';
}
}
@@ -82,7 +82,8 @@ public static function get_items( $args = [], $return_count = false ) {
runs.id,
$run_title,
runs.tests,
- runs.alerts,
+ SUM( IF( alerts.id IS NOT NULL, 1, 0 ) ) as alerts_count,
+ SUM( IF( alerts.id IS NOT NULL and alerts.alert_state = 0, 1, 0 ) ) as unread_alerts_count,
runs.trigger,
runs.trigger_notes,
runs.trigger_meta,
@@ -90,6 +91,9 @@ public static function get_items( $args = [], $return_count = false ) {
runs.scheduled_at,
runs.finished_at
FROM $test_runs_table as runs
+ LEFT JOIN $alerts_table as alerts
+ ON runs.id = alerts.test_run_id
+ GROUP BY runs.id
) runs
$where
$orderby
@@ -372,7 +376,7 @@ public static function get_calculated_status( $test_run ) {
$test_run = self::get_item( $test_run );
}
- $has_alerts = ! empty( maybe_unserialize( $test_run->alerts ) );
+ $has_alerts = ( $test_run->alerts_count ?? 0 ) > 0;
if ( $has_alerts ) {
return 'has-alerts';
@@ -440,7 +444,7 @@ public static function get_status_data( $test_run ) {
switch ( $test_run_status ) {
case 'has-alerts':
- $alerts_count = count( maybe_unserialize( $test_run->alerts ) );
+ $alerts_count = $test_run->alerts_count;
$class = 'paused';
$text = esc_html__( 'Changes detected', 'visual-regression-tests' );
$instructions = Date_Time_Helpers::get_formatted_relative_date_time( $test_run->finished_at );
diff --git a/includes/services/class-test-run-service.php b/includes/services/class-test-run-service.php
index 9c3a2b0..0b35581 100644
--- a/includes/services/class-test-run-service.php
+++ b/includes/services/class-test-run-service.php
@@ -5,6 +5,7 @@
use Vrts\Core\Utilities\Url_Helpers;
use Vrts\Features\Service;
use Vrts\Features\Subscription;
+use Vrts\Models\Alert;
use Vrts\Models\Test;
use Vrts\Models\Test_Run;
use Vrts\Services\Email_Service;
@@ -23,7 +24,6 @@ public function update_run_from_api_data( $data ) {
$test_run = Test_Run::get_by_service_test_run_id( $run_id );
$test_run_just_finished = false;
- $alert_ids = [];
if ( $test_run && empty( $test_run->finished_at ) && ! empty( $data['finished_at'] ) ) {
$test_run_just_finished = true;
@@ -41,7 +41,6 @@ public function update_run_from_api_data( $data ) {
$test_run_id = $this->create_test_run( $data['run_id'], [
'tests' => maybe_serialize( $test_ids ),
- 'alerts' => ! empty( $alert_ids ) ? maybe_serialize( $alert_ids ) : null,
'started_at' => $data['started_at'],
'finished_at' => $data['finished_at'],
'scheduled_at' => $data['scheduled_at'],
diff --git a/includes/tables/class-test-runs-table.php b/includes/tables/class-test-runs-table.php
index e307c71..bb31e39 100644
--- a/includes/tables/class-test-runs-table.php
+++ b/includes/tables/class-test-runs-table.php
@@ -4,7 +4,7 @@
class Test_Runs_Table {
- const DB_VERSION = '1.0';
+ const DB_VERSION = '1.1';
const TABLE_NAME = 'vrts_test_runs';
/**
@@ -32,7 +32,6 @@ public static function install_table() {
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
service_test_run_id varchar(40),
tests text,
- alerts text default NULL,
`trigger` varchar(20),
trigger_notes text,
trigger_meta text default NULL,
@@ -106,7 +105,7 @@ public static function create_runs_from_alerts() {
'permalink' => get_permalink( $alert->post_id ),
],
] ),
- 'alerts' => maybe_serialize( [ $alert->id ] ),
+ 'alert_id' => $alert->id,
'trigger' => 'legacy',
'started_at' => $alert->finished_at,
'finished_at' => $alert->finished_at,
@@ -117,13 +116,21 @@ public static function create_runs_from_alerts() {
return "('" . implode( "','", array_map( 'esc_sql', $run ) ) . "')";
}, $test_runs));
+ // add alert_id column to test_runs table.
+ // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange
+ $wpdb->query( "ALTER TABLE {$runs_table} ADD COLUMN alert_id bigint(20) unsigned;" );
+
// insert all test runs with single query.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
- $wpdb->query( "INSERT INTO {$runs_table} (tests, alerts, `trigger`, started_at, finished_at) VALUES " . $test_runs_values . ';' );
+ $wpdb->query( "INSERT INTO {$runs_table} (tests, alert_id, `trigger`, started_at, finished_at) VALUES " . $test_runs_values . ';' );
- // update test_run_id in alerts table from newly created test runs based on alerts column.
+ // update test_run_id in alerts table from newly created test runs based on alert_id column.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
- $wpdb->query( "UPDATE {$alerts_table} a JOIN {$runs_table} r ON r.alerts LIKE CONCAT('%\"', a.id, '\"%') SET a.test_run_id = r.id;" );
+ $wpdb->query( "UPDATE {$alerts_table} a JOIN {$runs_table} r ON r.alert_id = a.id SET a.test_run_id = r.id;" );
+
+ // remove alert_id column from test_runs table.
+ // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange
+ $wpdb->query( "ALTER TABLE {$runs_table} DROP COLUMN alert_id;" );
return true;
}