diff --git a/.eslintrc.js b/.eslintrc.js index ad36a2c..31a2999 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,6 +1,7 @@ 'use-strict'; module.exports = { + 'root': true, 'env': { 'browser': true, 'jquery': true diff --git a/tawkto/assets/js/tawk.admin.js b/tawkto/assets/js/tawk.admin.js index 22e4f03..0062cd2 100644 --- a/tawkto/assets/js/tawk.admin.js +++ b/tawkto/assets/js/tawk.admin.js @@ -72,6 +72,26 @@ jQuery( jQuery( this ).addClass( 'reverse' ); }); + + if ( jQuery( '#enable-visitor-recognition' ).prop( 'checked' ) ) { + jQuery( '.tawk-selected-visitor' ).show(); + jQuery( '#js-api-key' ).prop( 'disabled', false ); + } else { + jQuery( '.tawk-selected-visitor' ).hide(); + jQuery( '#js-api-key' ).prop( 'disabled', true ); + } + + jQuery( '#enable-visitor-recognition' ).change( + function() { + if ( this.checked ) { + jQuery( '.tawk-selected-visitor' ).fadeIn(); + jQuery( '#js-api-key' ).prop( 'disabled', false ); + } else { + jQuery( '.tawk-selected-visitor' ).fadeOut(); + jQuery( '#js-api-key' ).prop( 'disabled', true ); + } + } + ); } ); diff --git a/tawkto/includes/default_config.php b/tawkto/includes/default_config.php index 1658e85..2312721 100644 --- a/tawkto/includes/default_config.php +++ b/tawkto/includes/default_config.php @@ -15,6 +15,11 @@ 'display_on_productcategory' => 0, 'display_on_productpage' => 0, 'display_on_producttag' => 0, + ), + 'privacy' => array( 'enable_visitor_recognition' => 1, ), + 'security' => array( + 'js_api_key' => '', + ), ); diff --git a/tawkto/tawkto.php b/tawkto/tawkto.php index 444fba6..fbb91d2 100644 --- a/tawkto/tawkto.php +++ b/tawkto/tawkto.php @@ -25,8 +25,14 @@ class TawkTo_Settings { const TAWK_WIDGET_ID_VARIABLE = 'tawkto-embed-widget-widget-id'; const TAWK_PAGE_ID_VARIABLE = 'tawkto-embed-widget-page-id'; const TAWK_VISIBILITY_OPTIONS = 'tawkto-visibility-options'; + const TAWK_PRIVACY_OPTIONS = 'tawkto-privacy-options'; + const TAWK_SECURITY_OPTIONS = 'tawkto-security-options'; const TAWK_ACTION_SET_WIDGET = 'tawkto-set-widget'; const TAWK_ACTION_REMOVE_WIDGET = 'tawkto-remove-widget'; + const CIPHER = 'AES-256-CBC'; + const CIPHER_IV_LENGTH = 16; + const NO_CHANGE = 'nochange'; + const TAWK_API_KEY = 'tawkto-js-api-key'; /** * @var $plugin_ver Plugin version @@ -39,11 +45,7 @@ class TawkTo_Settings { * @return void */ public function __construct() { - if ( ! get_option( self::TAWK_VISIBILITY_OPTIONS, false ) ) { - $visibility = self::get_default_visibility_options(); - - update_option( self::TAWK_VISIBILITY_OPTIONS, $visibility ); - } + self::init_options(); add_action( 'wp_loaded', array( &$this, 'init' ) ); add_action( 'admin_init', array( &$this, 'admin_init' ) ); @@ -71,6 +73,27 @@ public function init() { } } + /** + * Initialize default option values + * + * @return void + */ + public static function init_options() { + $options = self::get_default_options(); + + if ( ! get_option( self::TAWK_VISIBILITY_OPTIONS, false ) ) { + update_option( self::TAWK_VISIBILITY_OPTIONS, $options['visibility'] ); + } + + if ( ! get_option( self::TAWK_PRIVACY_OPTIONS, false ) ) { + update_option( self::TAWK_PRIVACY_OPTIONS, $options['privacy'] ); + } + + if ( ! get_option( self::TAWK_SECURITY_OPTIONS, false ) ) { + update_option( self::TAWK_SECURITY_OPTIONS, $options['security'] ); + } + } + /** * Retrieves tawk.to admin settings assets * @@ -106,7 +129,9 @@ public function tawk_settings_assets( $hook ) { * @return void */ public function admin_init() { - register_setting( 'tawk_options', self::TAWK_VISIBILITY_OPTIONS, array( &$this, 'validate_options' ) ); + register_setting( 'tawk_options', self::TAWK_VISIBILITY_OPTIONS, array( &$this, 'validate_visibility_options' ) ); + register_setting( 'tawk_options', self::TAWK_PRIVACY_OPTIONS, array( &$this, 'validate_privacy_options' ) ); + register_setting( 'tawk_options', self::TAWK_SECURITY_OPTIONS, array( &$this, 'validate_security_options' ) ); } /** @@ -228,10 +253,10 @@ private function validate_request_auth( $action, $post_data = array() ) { * Validates the selected visibility options * * @param array $input - Visibility option fields. - * @return boolean + * @return mixed */ - public function validate_options( $input ) { - $visibility_toggle_fields = array( + public function validate_visibility_options( $input ) { + $toggle_fields = array( 'always_display', 'show_onfrontpage', 'show_oncategory', @@ -243,18 +268,62 @@ public function validate_options( $input ) { 'display_on_productcategory', 'display_on_productpage', 'display_on_producttag', - 'enable_visitor_recognition', ); - $visibility_text_fields = array( + $text_fields = array( 'excluded_url_list', 'included_url_list', ); - self::validate_visibility_toggle_fields( $input, $visibility_toggle_fields ); - self::validate_text_fields( $input, $visibility_text_fields ); + $visibility = get_option( self::TAWK_VISIBILITY_OPTIONS, array() ); + + self::validate_toggle_fields( $input, $toggle_fields ); + self::validate_text_fields( $input, $text_fields ); + + $visibility = array_merge( $visibility, $input ); + + return $visibility; + } + + /** + * Validates the selected privacy options + * + * @param mixed $input - Privacy option fields. + * @return mixed + */ + public function validate_privacy_options( $input ) { + $toggle_fields = array( + 'enable_visitor_recognition', + ); + + $privacy = get_option( self::TAWK_PRIVACY_OPTIONS, array() ); + + self::validate_toggle_fields( $input, $toggle_fields ); + + $privacy = array_merge( $privacy, $input ); + + return $privacy; + } + + /** + * Validates the selected security options + * + * @param mixed $input - Security option fields. + * @return mixed + */ + public function validate_security_options( $input ) { + $text_fields = array( + 'js_api_key', + ); + + $security = get_option( self::TAWK_SECURITY_OPTIONS, array() ); + + self::validate_text_fields( $input, $text_fields ); + self::validate_js_api_key( $input ); - return $input; + $security = array_merge( $security, $input ); + + return $security; } /** @@ -294,15 +363,33 @@ public function create_plugin_settings_page() { $remove_widget_nonce = wp_create_nonce( self::TAWK_ACTION_REMOVE_WIDGET ); $plugin_ver = $this->plugin_ver; - $default_visibility = self::get_default_visibility_options(); - $visibility = get_option( self::TAWK_VISIBILITY_OPTIONS, array() ); + $default_options = self::get_default_options(); + $visibility = get_option( self::TAWK_VISIBILITY_OPTIONS, array() ); + $privacy = get_option( self::TAWK_PRIVACY_OPTIONS, array() ); + $security = get_option( self::TAWK_SECURITY_OPTIONS, array() ); - foreach ( $default_visibility as $key => $value ) { + foreach ( $default_options['visibility'] as $key => $value ) { if ( ! isset( $visibility[ $key ] ) ) { $visibility[ $key ] = $value; } } + foreach ( $default_options['privacy'] as $key => $value ) { + if ( ! isset( $privacy[ $key ] ) ) { + $privacy[ $key ] = $value; + } + } + + foreach ( $default_options['security'] as $key => $value ) { + if ( ! isset( $security[ $key ] ) ) { + $security[ $key ] = $value; + } + } + + if ( ! empty( $security['js_api_key'] ) ) { + $security['js_api_key'] = self::NO_CHANGE; + } + include sprintf( '%s/templates/settings.php', dirname( __FILE__ ) ); } @@ -318,6 +405,38 @@ public static function ids_are_correct( $page_id, $widget_id ) { return 1 === preg_match( '/^[0-9A-Fa-f]{24}$/', $page_id ) && 1 === preg_match( '/^[a-z0-9]{1,50}$/i', $widget_id ); } + /** + * Validate JS API Key field + * + * @param array $fields - List of fields. + * @return void + * @throws Exception - Error validating JS API Key. + */ + private static function validate_js_api_key( &$fields ) { + if ( self::NO_CHANGE === $fields['js_api_key'] ) { + unset( $fields['js_api_key'] ); + return; + } + + delete_transient( self::TAWK_API_KEY ); + + if ( '' === $fields['js_api_key'] ) { + return; + } + + try { + if ( 40 !== strlen( $fields['js_api_key'] ) ) { + throw new Exception( 'Invalid key. Please provide value with 40 characters' ); + } + + $fields['js_api_key'] = self::get_encrypted_data( $fields['js_api_key'] ); + } catch ( Exception $e ) { + self::show_tawk_options_error( 'Javascript API Key: ' . $e->getMessage() ); + + unset( $fields['js_api_key'] ); + } + } + /** * Validates and sanitizes text fields * @@ -343,7 +462,7 @@ private static function validate_text_fields( &$fields, $field_names ) { * @param array $field_names - List of field names to be validated. * @return void */ - private static function validate_visibility_toggle_fields( &$fields, $field_names ) { + private static function validate_toggle_fields( &$fields, $field_names ) { foreach ( $field_names as $field_name ) { if ( isset( $fields[ $field_name ] ) && '1' === $fields[ $field_name ] ) { $fields[ $field_name ] = 1; @@ -359,12 +478,109 @@ private static function validate_visibility_toggle_fields( &$fields, $field_name * * @return array */ - public static function get_default_visibility_options() { + public static function get_default_options() { $config = include plugin_dir_path( __FILE__ ) . 'includes/default_config.php'; - return $config['visibility']; + return $config; + } + + /** + * Encrypt data + * + * @param string $data - Data to be encrypted. + * @return string + * @throws Exception - Error encrypting data. + */ + private static function get_encrypted_data( $data ) { + if ( ! defined( 'SECURE_AUTH_KEY' ) ) { + throw new Exception( 'SECURE_AUTH_KEY is not defined' ); + } + + try { + $iv = random_bytes( self::CIPHER_IV_LENGTH ); + } catch ( Exception $e ) { + throw new Exception( 'Error generating IV' ); + } + + $encrypted_data = openssl_encrypt( $data, self::CIPHER, SECURE_AUTH_KEY, 0, $iv ); + + if ( false === $encrypted_data ) { + throw new Exception( 'Error encrypting data' ); + } + + // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode + $encrypted_data = base64_encode( $iv . $encrypted_data ); + + if ( false === $encrypted_data ) { + throw new Exception( 'Error encoding data' ); + } + + return $encrypted_data; + } + + /** + * Decrypt data + * + * @param string $data - Data to be decrypted. + * @return string + */ + private static function get_decrypted_data( $data ) { + // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode + $decoded_data = base64_decode( $data ); + + if ( false === $decoded_data ) { + return ''; + } + + $iv = substr( $decoded_data, 0, self::CIPHER_IV_LENGTH ); + $encrypted_data = substr( $decoded_data, self::CIPHER_IV_LENGTH ); + + $decrypted_data = openssl_decrypt( $encrypted_data, self::CIPHER, SECURE_AUTH_KEY, 0, $iv ); + + if ( false === $decrypted_data ) { + return ''; + } + + return $decrypted_data; + } + + /** + * Retrieves JS API Key + * + * @return string + */ + public static function get_js_api_key() { + if ( ! empty( get_transient( self::TAWK_API_KEY ) ) ) { + return get_transient( self::TAWK_API_KEY ); + } + + $security = get_option( self::TAWK_SECURITY_OPTIONS ); + + if ( ! isset( $security['js_api_key'] ) ) { + return ''; + } + + $key = self::get_decrypted_data( $security['js_api_key'] ); + + set_transient( self::TAWK_API_KEY, $key, 60 * 60 ); + + return $key; } + /** + * Adds settings error + * + * @param string $message - Error message. + * @return void + */ + private static function show_tawk_options_error( $message ) { + add_settings_error( + 'tawk_options', + 'tawk_error', + $message, + 'error' + ); + } } } @@ -426,11 +642,10 @@ public static function get_plugin_version() { public static function activate() { global $plugin_file_data; - $visibility = TawkTo_Settings::get_default_visibility_options(); + TawkTo_Settings::init_options(); add_option( TawkTo_Settings::TAWK_PAGE_ID_VARIABLE, '', '', 'yes' ); add_option( TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE, '', '', 'yes' ); - add_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS, $visibility, '', 'yes' ); add_option( self::PLUGIN_VERSION_VARIABLE, self::get_plugin_version(), '', 'yes' ); } @@ -441,7 +656,11 @@ public static function deactivate() { delete_option( TawkTo_Settings::TAWK_PAGE_ID_VARIABLE ); delete_option( TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE ); delete_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS ); + delete_option( TawkTo_Settings::TAWK_PRIVACY_OPTIONS ); + delete_option( TawkTo_Settings::TAWK_SECURITY_OPTIONS ); delete_option( self::PLUGIN_VERSION_VARIABLE ); + + delete_transient( TawkTo_Settings::TAWK_API_KEY ); } /** @@ -463,6 +682,12 @@ public function get_current_customer_details() { 'name' => $current_user->display_name, 'email' => $current_user->user_email, ); + + $js_api_key = TawkTo_Settings::get_js_api_key(); + if ( ! empty( $user_info['email'] ) && ! empty( $js_api_key ) ) { + $user_info['hash'] = hash_hmac( 'sha256', $user_info['email'], $js_api_key ); + } + return wp_json_encode( $user_info ); } return null; @@ -472,15 +697,15 @@ public function get_current_customer_details() { * Creates the embed code */ public function embed_code() { - $page_id = get_option( TawkTo_Settings::TAWK_PAGE_ID_VARIABLE ); - $widget_id = get_option( TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE ); - $visibility = get_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS ); + $page_id = get_option( TawkTo_Settings::TAWK_PAGE_ID_VARIABLE ); + $widget_id = get_option( TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE ); + $privacy = get_option( TawkTo_Settings::TAWK_PRIVACY_OPTIONS ); // default value. $enable_visitor_recognition = true; - if ( isset( $visibility ) && isset( $visibility['enable_visitor_recognition'] ) ) { - $enable_visitor_recognition = 1 === $visibility['enable_visitor_recognition']; + if ( isset( $privacy ) && isset( $privacy['enable_visitor_recognition'] ) ) { + $enable_visitor_recognition = 1 === $privacy['enable_visitor_recognition']; } if ( $enable_visitor_recognition ) { @@ -523,51 +748,51 @@ private function get_current_url() { * @return void */ public function print_embed_code() { - $vsibility = get_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS ); - $display = false; + $visibility = get_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS ); + $display = false; - if ( 1 === $vsibility['always_display'] ) { + if ( 1 === $visibility['always_display'] ) { $display = true; } - if ( ( 1 === $vsibility['show_onfrontpage'] ) && ( is_home() || is_front_page() ) ) { + if ( ( 1 === $visibility['show_onfrontpage'] ) && ( is_home() || is_front_page() ) ) { $display = true; } - if ( ( 1 === $vsibility['show_oncategory'] ) && is_category() ) { + if ( ( 1 === $visibility['show_oncategory'] ) && is_category() ) { $display = true; } - if ( ( 1 === $vsibility['show_ontagpage'] ) && is_tag() ) { + if ( ( 1 === $visibility['show_ontagpage'] ) && is_tag() ) { $display = true; } - if ( ( 1 === $vsibility['show_onarticlepages'] ) && is_single() ) { + if ( ( 1 === $visibility['show_onarticlepages'] ) && is_single() ) { $display = true; } if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ), true ) ) { - if ( ( 1 === $vsibility['display_on_shop'] ) && is_shop() ) { + if ( ( 1 === $visibility['display_on_shop'] ) && is_shop() ) { $display = true; } - if ( ( 1 === $vsibility['display_on_productcategory'] ) && is_product_category() ) { + if ( ( 1 === $visibility['display_on_productcategory'] ) && is_product_category() ) { $display = true; } - if ( ( 1 === $vsibility['display_on_productpage'] ) && is_product() ) { + if ( ( 1 === $visibility['display_on_productpage'] ) && is_product() ) { $display = true; } - if ( ( 1 === $vsibility['display_on_producttag'] ) && is_product_tag() ) { + if ( ( 1 === $visibility['display_on_producttag'] ) && is_product_tag() ) { $display = true; } } - if ( isset( $vsibility['include_url'] ) && 1 === $vsibility['include_url'] ) { + if ( isset( $visibility['include_url'] ) && 1 === $visibility['include_url'] ) { $current_url = $this->get_current_url(); - $included_url_list = $vsibility['included_url_list']; + $included_url_list = $visibility['included_url_list']; $included_url_list = array_map( 'trim', preg_split( '/,/', $included_url_list ) ); if ( UrlPatternMatcher::match( $current_url, $included_url_list ) ) { @@ -575,10 +800,10 @@ public function print_embed_code() { } } - if ( isset( $vsibility['exclude_url'] ) && ( 1 === $vsibility['exclude_url'] ) ) { + if ( isset( $visibility['exclude_url'] ) && ( 1 === $visibility['exclude_url'] ) ) { $current_url = $this->get_current_url(); - $excluded_url_list = $vsibility['excluded_url_list']; + $excluded_url_list = $visibility['excluded_url_list']; $excluded_url_list = array_map( 'trim', preg_split( '/,/', $excluded_url_list ) ); if ( UrlPatternMatcher::match( $current_url, $excluded_url_list ) ) { diff --git a/tawkto/templates/settings.php b/tawkto/templates/settings.php index 47650e3..7e2ad42 100644 --- a/tawkto/templates/settings.php +++ b/tawkto/templates/settings.php @@ -404,14 +404,37 @@ class="slider round" /> + />
+ +
+

+ +

+ + + + + + +
+ + + +
+
diff --git a/tawkto/upgrade.manager.php b/tawkto/upgrade.manager.php index bc720cd..7f7af50 100644 --- a/tawkto/upgrade.manager.php +++ b/tawkto/upgrade.manager.php @@ -1,6 +1,7 @@ upgrades = array( TawkToUpgradeVersion070::get_version() => TawkToUpgradeVersion070::class, + TawkToUpgradeVersion090::get_version() => TawkToUpgradeVersion090::class, ); $this->version_var_name = $version_var_name; diff --git a/tawkto/upgrades/version.090.php b/tawkto/upgrades/version.090.php new file mode 100644 index 0000000..2c41eeb --- /dev/null +++ b/tawkto/upgrades/version.090.php @@ -0,0 +1,30 @@ + $visibility['enable_visitor_recognition'] ) ); + + unset( $visibility['enable_visitor_recognition'] ); + update_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS, $visibility ); + } + + update_option( TawkTo_Settings::TAWK_SECURITY_OPTIONS, array( 'js_api_key' => '' ) ); + } +} diff --git a/tests/Coverages/PrivacyOptionsTest.php b/tests/Coverages/PrivacyOptionsTest.php index db6c27e..fb1e54f 100644 --- a/tests/Coverages/PrivacyOptionsTest.php +++ b/tests/Coverages/PrivacyOptionsTest.php @@ -35,6 +35,7 @@ public static function setupBeforeClass(): void { public function setup(): void { self::$web->login(); + self::$web->goto_privacy_options(); } public static function tearDownAfterClass(): void { @@ -60,6 +61,7 @@ public function should_have_data_on_visitor_object_if_logged_in(): void { $this->assertNotEmpty( $visitor_data ); $this->assertEquals( self::$admin_name, $visitor_data['name'] ); $this->assertEquals( self::$admin_email, $visitor_data['email'] ); + $this->assertArrayNotHasKey( 'hash', $visitor_data ); } /** @@ -76,4 +78,27 @@ public function should_not_have_data_on_visitor_object_if_not_logged_in(): void $this->assertEmpty( $visitor_data ); } + + /** + * @test + * @group privacy_options + */ + public function should_have_hash_on_visitor_object_if_logged_in_and_api_key_provided(): void { + self::$web->toggle_switch( '#enable-visitor-recognition', true ); + self::$driver->find_element_and_input( '#js-api-key', str_repeat( 'a', 40 ) ); + + self::$driver->move_mouse_to( '#submit-header' )->click(); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); + + self::$driver->goto_page( self::$web->get_base_url() ); + + self::$driver->wait_until_element_is_located( self::$script_selector ); + + $visitor_data = self::$driver->get_driver()->executeScript( 'return Tawk_API.visitor' ); + + $this->assertNotEmpty( $visitor_data ); + $this->assertEquals( self::$admin_name, $visitor_data['name'] ); + $this->assertEquals( self::$admin_email, $visitor_data['email'] ); + $this->assertArrayHasKey( 'hash', $visitor_data ); + } } diff --git a/tests/Coverages/VisibilityOptionsTest.php b/tests/Coverages/VisibilityOptionsTest.php index a39284a..ea1ab0e 100644 --- a/tests/Coverages/VisibilityOptionsTest.php +++ b/tests/Coverages/VisibilityOptionsTest.php @@ -78,7 +78,7 @@ public function should_not_display_widget_on_excluded_page_while_always_display_ self::$driver->find_element_and_input( '#excluded-url-list', $excluded_url ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_not_on_page( $excluded_url ); } @@ -106,7 +106,7 @@ public function should_not_display_widget_on_excluded_pages_match_by_wildcard_wh self::$driver->find_element_and_input( '#excluded-url-list', $excluded_urls ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); // assertion for '/category/*'. $this->check_widget_not_on_page( self::$web->get_base_url() . 'category/category-a/' ); @@ -161,7 +161,7 @@ public function should_display_widget_on_non_excluded_pages_while_always_display self::$driver->find_element_and_input( '#excluded-url-list', $excluded_url ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( self::$web->get_base_url() . 'tag/tag-a/' ); } @@ -173,7 +173,7 @@ public function should_display_widget_on_non_excluded_pages_while_always_display public function should_not_display_when_always_display_is_disabled() { self::$web->toggle_switch( '#always-display', false ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_not_on_page( self::$web->get_base_url() ); } @@ -189,7 +189,7 @@ public function should_display_widget_on_included_page_while_always_display_is_d self::$driver->find_element_and_input( '#included-url-list', $included_url ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( $included_url ); } @@ -218,7 +218,7 @@ public function should_display_widget_on_included_pages_matched_by_wildcard_whil self::$driver->find_element_and_input( '#included-url-list', $included_urls ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); // assertion for '/category/*'. $this->check_widget_on_page( self::$web->get_base_url() . 'category/category-a/' ); @@ -274,7 +274,7 @@ public function should_display_widget_on_non_included_pages_while_always_display self::$driver->find_element_and_input( '#included-url-list', $included_url ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_not_on_page( self::$web->get_base_url() . 'tag/tag-a/' ); } @@ -288,7 +288,7 @@ public function should_display_widget_on_front_page_if_show_on_front_page_is_ena self::$web->toggle_switch( '#show-onfrontpage', true ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( self::$web->get_base_url() ); } @@ -304,7 +304,7 @@ public function should_not_display_widget_on_front_page_if_excluded() { self::$driver->find_element_and_input( '#excluded-url-list', self::$web->get_base_url() ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_not_on_page( self::$web->get_base_url() ); } @@ -318,7 +318,7 @@ public function should_display_widget_on_category_pages_if_show_on_category_page self::$web->toggle_switch( '#show-oncategory', true ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( self::$web->get_base_url() . 'category/category-a/' ); $this->check_widget_on_page( self::$web->get_base_url() . 'category/category-b/' ); @@ -339,7 +339,7 @@ public function should_not_display_widget_on_category_pages_if_excluded() { self::$driver->find_element_and_input( '#excluded-url-list', $excluded_urls ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_not_on_page( $category_a_url ); $this->check_widget_not_on_page( $category_b_url ); @@ -354,7 +354,7 @@ public function should_display_widget_on_tag_pages_if_show_on_tag_pages_is_enabl self::$web->toggle_switch( '#show-ontagpage', true ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( self::$web->get_base_url() . 'tag/tag-a/' ); $this->check_widget_on_page( self::$web->get_base_url() . 'tag/tag-b/' ); @@ -375,7 +375,7 @@ public function should_not_display_widget_on_tag_pages_if_excluded() { self::$driver->find_element_and_input( '#excluded-url-list', $excluded_urls ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_not_on_page( $tag_a_url ); $this->check_widget_not_on_page( $tag_b_url ); @@ -390,7 +390,7 @@ public function should_display_widget_on_single_post_pages_if_show_on_single_pos self::$web->toggle_switch( '#show-onarticlepages', true ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( self::$web->get_base_url() . 'hello-world/' ); } @@ -408,7 +408,7 @@ public function should_not_display_widget_on_single_post_pages_if_excluded() { self::$driver->find_element_and_input( '#excluded-url-list', $excluded_url ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_not_on_page( $excluded_url ); } diff --git a/tests/Coverages/WoocommerceOptionsTest.php b/tests/Coverages/WoocommerceOptionsTest.php index 1d9b300..b8e9564 100644 --- a/tests/Coverages/WoocommerceOptionsTest.php +++ b/tests/Coverages/WoocommerceOptionsTest.php @@ -82,7 +82,7 @@ public function should_display_widget_on_shop_main_page_if_option_is_enabled() { self::$web->toggle_switch( '#display-on-shop', true ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( self::$web->get_base_url() . 'shop/' ); } @@ -98,7 +98,7 @@ public function should_display_widget_on_shop_main_page_if_option_is_disabled_an self::$web->toggle_switch( '#always-display', true ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( self::$web->get_base_url() . 'shop/' ); } @@ -111,7 +111,7 @@ public function should_not_display_widget_on_shop_main_page_if_option_is_disable self::$web->toggle_switch( '#display-on-shop', false ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_not_on_page( self::$web->get_base_url() . 'shop/' ); } @@ -124,7 +124,7 @@ public function should_display_widget_on_product_category_if_option_is_enabled() self::$web->toggle_switch( '#display-on-productcategory', true ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( self::$web->get_base_url() . 'product-category/music/' ); } @@ -140,7 +140,7 @@ public function should_display_widget_on_product_category_if_option_is_disabled_ self::$web->toggle_switch( '#always-display', true ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( self::$web->get_base_url() . 'product-category/music/' ); } @@ -153,7 +153,7 @@ public function should_not_display_widget_on_product_category_if_option_is_disab self::$web->toggle_switch( '#display-on-productcategory', false ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_not_on_page( self::$web->get_base_url() . 'product-category/music/' ); } @@ -166,7 +166,7 @@ public function should_display_widget_on_product_page_if_option_is_enabled() { self::$web->toggle_switch( '#display-on-productpage', true ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( self::$web->get_base_url() . 'product/album/' ); } @@ -182,7 +182,7 @@ public function should_display_widget_on_product_page_if_option_is_disabled_and_ self::$web->toggle_switch( '#always-display', true ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( self::$web->get_base_url() . 'product/album/' ); } @@ -195,7 +195,7 @@ public function should_not_display_widget_on_product_page_if_option_is_disabled( self::$web->toggle_switch( '#display-on-productpage', false ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_not_on_page( self::$web->get_base_url() . 'product/album/' ); } @@ -208,7 +208,7 @@ public function should_display_widget_on_product_tag_if_option_is_enabled() { self::$web->toggle_switch( '#display-on-producttag', true ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( self::$web->get_base_url() . 'product-tag/product-tag-a/' ); } @@ -224,7 +224,7 @@ public function should_display_widget_on_product_tag_if_option_is_disabled_and_a self::$web->toggle_switch( '#always-display', true ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_on_page( self::$web->get_base_url() . 'product-tag/product-tag-a/' ); } @@ -237,7 +237,7 @@ public function should_not_display_widget_on_product_tag_if_option_is_disabled() self::$web->toggle_switch( '#display-on-producttag', false ); self::$driver->move_mouse_to( '#submit-header' )->click(); - self::$driver->wait_for_seconds( 1 ); + self::$driver->wait_until_element_is_located( '#setting-error-settings_updated' ); $this->check_widget_not_on_page( self::$web->get_base_url() . 'product-tag/product-tag-a/' ); } diff --git a/tests/TestFiles/Modules/Web.php b/tests/TestFiles/Modules/Web.php index 831a197..d4a049f 100644 --- a/tests/TestFiles/Modules/Web.php +++ b/tests/TestFiles/Modules/Web.php @@ -70,8 +70,6 @@ public function login() { $this->driver->find_element_and_input( '#user_pass', $this->admin->password ); $this->driver->find_element_and_click( '#wp-submit' ); - $this->driver->wait_for_seconds( 1 ); - $this->driver->wait_until_page_fully_loads(); // prevent reauth=1 loop. @@ -241,7 +239,7 @@ public function set_widget( $property_id, $widget_id ) { $this->driver->find_element_and_click( '#addWidgetToPage' ); // ensures widget is added. - $this->driver->wait_for_seconds( 1 ); + $this->driver->wait_until_element_is_located( '#successMessage' ); $this->widget_set = true; @@ -260,7 +258,7 @@ public function remove_widget() { $this->driver->find_element_and_click( '#removeCurrentWidget' ); // ensures widget is added. - $this->driver->wait_for_seconds( 1 ); + $this->driver->wait_until_element_is_located( '#successMessage' ); $this->widget_set = false; @@ -289,7 +287,7 @@ public function reset_visibility_options( $save_flag = true ) { if ( $save_flag ) { $this->driver->move_mouse_to( '#submit-header' )->click(); - $this->driver->wait_for_seconds( 1 ); + $this->driver->wait_until_element_is_located( '#setting-error-settings_updated' ); } } @@ -302,7 +300,7 @@ public function reset_woocommerce_options( $save_flag = true ) { if ( $save_flag ) { $this->driver->move_mouse_to( '#submit-header' )->click(); - $this->driver->wait_for_seconds( 1 ); + $this->driver->wait_until_element_is_located( '#setting-error-settings_updated' ); } } diff --git a/tests/docker/build/files/build-wordpress.sh b/tests/docker/build/files/build-wordpress.sh index bf3ee24..18d5a12 100755 --- a/tests/docker/build/files/build-wordpress.sh +++ b/tests/docker/build/files/build-wordpress.sh @@ -72,4 +72,5 @@ wp option set woocommerce_store_postalcode 'A1B2C3' && \ wp option set woocommerce_currency 'CAD' && \ wp option set woocommerce_product_type 'physical' && \ wp option set woocommerce_allow_tracking 'no' && \ +wp option set woocommerce_coming_soon 'no' && \ wp wc --user=admin tool run install_pages;