diff --git a/admin/class-ajax.php b/admin/class-ajax.php
index ecae7831..c292294c 100644
--- a/admin/class-ajax.php
+++ b/admin/class-ajax.php
@@ -7,6 +7,7 @@
namespace EDAC\Admin;
+use EDAC\Admin\OptIn\Email_Opt_In;
use EDAC\Inc\Summary_Generator;
/**
@@ -33,7 +34,7 @@ public function init_hooks() {
add_action( 'wp_ajax_edac_update_simplified_summary', array( $this, 'simplified_summary' ) );
add_action( 'wp_ajax_edac_dismiss_welcome_cta_ajax', array( $this, 'dismiss_welcome_cta' ) );
add_action( 'wp_ajax_edac_dismiss_dashboard_cta_ajax', array( $this, 'dismiss_dashboard_cta' ) );
- add_action( 'wp_ajax_edac_email_opt_in_ajax', array( $this, 'email_opt_in' ) );
+ ( new Email_Opt_In() )->register_ajax_handlers();
}
/**
@@ -313,25 +314,25 @@ function ( $a, $b ) {
$html .= '
';
- $html .= '
';
+ $html .= '
';
- $html .= '
';
- $html .= '' . $rule['count'] . ' ';
- $html .= esc_html( $rule['title'] );
+ $html .= '';
+ $html .= '' . $rule['count'] . ' ';
+ $html .= esc_html( $rule['title'] );
if ( $count_ignored > 0 ) {
$html .= '' . $count_ignored . ' Ignored Items ';
}
- $html .= ' ';
- $html .= ' ';
- $html .= ( $expand_rule ) ? ' ' : '';
+ $html .= ' ';
+ $html .= '
';
+ $html .= ( $expand_rule ) ? '
' : '';
- $html .= '
';
+ $html .= '
';
if ( $results ) {
$html .= '
';
- $html .=
+ $html .=
'
Affected Code
@@ -387,13 +388,13 @@ function ( $a, $b ) {
$html .= '
';
- $html .= '
';
+ $html .= '
';
- $html .= '' . esc_html( $row['object'] ) . '
';
+ $html .= '' . esc_html( $row['object'] ) . '
';
- $html .= '
';
+ $html .= '
';
- $html .= '
';
+ $html .= '
';
if ( $object_img ) {
$html .= '
';
@@ -401,11 +402,11 @@ function ( $a, $b ) {
$html .= $object_svg;
}
- $html .= '
';
+ $html .= '
';
- $html .= '
';
+ $html .= '
';
- $html .= '
' . EDAC_SVG_IGNORE_ICON . '' . $ignore_label . ' ';
+ $html .= '
' . EDAC_SVG_IGNORE_ICON . '' . $ignore_label . ' ';
if ( 'missing_headings' !== $rule['slug'] ) {
@@ -420,18 +421,18 @@ function ( $a, $b ) {
$html .= '
View on page';
}
- $html .= '
';
+ $html .= '
';
- $html .= '
';
+ $html .= '
';
- $html .= '
';
- $html .= '
' . $ignore_username . ' ';
+ $html .= '
';
+ $html .= '' . $ignore_username . ' ';
- $html .= ' ' . $ignore_date . ' ';
- $html .= '
';
+ $html .= '
' . $ignore_date . ' ';
+ $html .= '
';
- $html .= ( true === $ignore_permission || ! empty( $ignore_comment ) ) ? '
Comment ' : '';
- $html .= ( true === $ignore_permission || ! empty( $ignore_comment ) ) ? '' : '';
+ $html .= ( true === $ignore_permission || ! empty( $ignore_comment ) ) ? '
Comment ' : '';
+ $html .= ( true === $ignore_permission || ! empty( $ignore_comment ) ) ? '' : '';
if ( $ignore_global ) {
$html .= ( true === $ignore_permission ) ? '
Manage Globally Ignored ' : '';
@@ -439,9 +440,9 @@ function ( $a, $b ) {
$html .= ( true === $ignore_permission ) ? '
' . EDAC_SVG_IGNORE_ICON . ' ' . $ignore_submit_label . ' ' : '';
}
- $html .= ( false === $ignore_permission && false === $ignore ) ? __( 'Your user account doesn\'t have permission to ignore this issue.', 'accessibility-checker' ) : '';
+ $html .= ( false === $ignore_permission && false === $ignore ) ? __( 'Your user account doesn\'t have permission to ignore this issue.', 'accessibility-checker' ) : '';
- $html .= '
';
+ $html .= '
';
$html .= '
';
@@ -539,7 +540,7 @@ public function readability() {
} else {
$html .= '
A simplified summary is not necessary when content reading level is 9th grade or below. Choose when to prompt for a simplified summary on the settings page.
';
}
- $html .= '';
+ $html .= '';
if ( $post_grade_failed ) {
@@ -554,7 +555,7 @@ public function readability() {
if ( 'none' === $simplified_summary_prompt ) {
$html .=
- '
+ '
Simplified summary is not being automatically inserted into the content.
Your Prompt for Simplified Summary is set to "never." If you would like the simplified summary to be displayed automatically, you can change this on the settings page .
@@ -563,7 +564,7 @@ public function readability() {
} elseif ( 'none' !== $simplified_summary_position ) {
$html .=
- '
+ '
Simplified summary is being automatically inserted ' . $simplified_summary_position . ' the content .
Set where the Simplified Summary is inserted into the content on the settings page .
@@ -572,7 +573,7 @@ public function readability() {
} else {
$html .=
- '
+ '
Simplified summary is not being automatically inserted into the content.
Your Simplified Summary location is set to "manually" which requires a function be added to your page template. If you would like the simplified summary to be displayed automatically, you can change this on the settings page .
@@ -585,7 +586,7 @@ public function readability() {
if ( ( $post_grade_failed || 'always' === $simplified_summary_prompt ) && ( 'none' !== $simplified_summary_prompt ) ) {
$html .=
- '
+ '
-
+
+
@@ -206,7 +208,7 @@
-
+
-
+
diff --git a/src/emailOptIn/index.js b/src/emailOptIn/index.js
index ce605184..23374c7f 100644
--- a/src/emailOptIn/index.js
+++ b/src/emailOptIn/index.js
@@ -1,5 +1,7 @@
/* eslint-disable */
+import {initOptInModal} from "./modal";
+
const edac_on_submit_ok = function () {
const data = { action: "edac_email_opt_in_ajax", nonce: edac_email_opt_in_form.nonce };
const queryString = Object.keys(data)
@@ -498,4 +500,8 @@ window._load_script = function (url, callback, isSubmit) {
return false;
};
addEvent(form_to_submit, 'submit', form_submit);
+ // Added in plugin version 1.11.0 and triggers through `window.onload` event.
+ if ( window.edac_email_opt_in_form.showModal ) {
+ initOptInModal();
+ }
})();
diff --git a/src/emailOptIn/modal.js b/src/emailOptIn/modal.js
new file mode 100644
index 00000000..cbc31c77
--- /dev/null
+++ b/src/emailOptIn/modal.js
@@ -0,0 +1,45 @@
+/**
+ * Handle the opt-in modal for first time visitors to welcome page.
+ *
+ * This relies on the Thickbox library that is included in WordPress core which relies on jQuery.
+ */
+
+/* global tb_show */
+
+import { createFocusTrap } from 'focus-trap';
+
+// Ensure the global variable is defined.
+window.edac_email_opt_in_form = window.edac_email_opt_in_form || {};
+
+export const initOptInModal = () => {
+ window.onload = function() {
+ tb_show( 'Accessibility Checker', '#TB_inline?width=600&inlineId=edac-opt-in-modal', null );
+
+ // a small delay is needed to ensure the modal is fully loaded before creating a focus trap.
+ setTimeout(
+ function() {
+ const modal = document.getElementById( 'TB_window' )
+ .querySelector( '.tb-close-icon' )
+ .setAttribute( 'aria-hidden', 'true' );
+
+ const focusTrap = createFocusTrap( modal );
+ focusTrap.activate();
+
+ jQuery( document ).one(
+ 'tb_unload',
+ function() {
+ onModalClose( focusTrap );
+ }
+ );
+ },
+ 200
+ );
+ };
+};
+
+const onModalClose = ( focusTrap ) => {
+ focusTrap.deactivate();
+
+ fetch( window.edac_email_opt_in_form.ajaxurl + '?action=edac_email_opt_in_closed_modal_ajax' )
+ .then( ( r ) => r.json() );
+};
diff --git a/src/emailOptIn/sass/email-opt-in.scss b/src/emailOptIn/sass/email-opt-in.scss
index c459e9e2..417ee123 100644
--- a/src/emailOptIn/sass/email-opt-in.scss
+++ b/src/emailOptIn/sass/email-opt-in.scss
@@ -1,116 +1,9 @@
-/*
+#_form_1_ {
+ padding: 0;
+ margin: 0;
+ input {
+ width: 100%;
+ }
+}
-// This is the original css provided by ActiveCampaign.
-@import url(https://fonts.bunny.net/css?family=ibm-plex-sans:400,600);
- #_form_1_ { font-size:14px; line-height:1.6; font-family:arial, helvetica, sans-serif; margin:0; }
- #_form_1_ * { outline:0; }
- ._form_hide { display:none; visibility:hidden; }
- ._form_show { display:block; visibility:visible; }
- #_form_1_._form-top { top:0; }
- #_form_1_._form-bottom { bottom:0; }
- #_form_1_._form-left { left:0; }
- #_form_1_._form-right { right:0; }
- #_form_1_ input[type="text"],#_form_1_ input[type="tel"],#_form_1_ input[type="date"],#_form_1_ textarea { padding:6px; height:auto; border:#979797 1px solid; border-radius:4px; color:#000 !important; font-size:14px; -webkit-box-sizing:border-box; -moz-box-sizing:border-box; box-sizing:border-box; }
- #_form_1_ textarea { resize:none; }
- #_form_1_ ._submit { -webkit-appearance:none; cursor:pointer; font-family:arial, sans-serif; font-size:14px; text-align:center; background:#015798 !important; border:0 !important; -moz-border-radius:4px !important; -webkit-border-radius:4px !important; border-radius:4px !important; color:#fff !important; padding:10px !important; }
- #_form_1_ ._submit:disabled { cursor:not-allowed; opacity:0.4; }
- #_form_1_ ._submit.processing { position:relative; }
- #_form_1_ ._submit.processing::before { content:''; width:1em; height:1em; position:absolute; z-index:1; top:50%; left:50%; border:double 3px transparent; border-radius:50%; background-image:linear-gradient(#015798, #015798), conic-gradient(#015798, #fff); background-origin:border-box; background-clip:content-box, border-box; animation:1200ms ease 0s infinite normal none running _spin; }
- #_form_1_ ._submit.processing::after { content:''; position:absolute; top:0; bottom:0; left:0; right:0; background:#015798 !important; border:0 !important; -moz-border-radius:4px !important; -webkit-border-radius:4px !important; border-radius:4px !important; color:#fff !important; padding:10px !important; }
- @keyframes _spin { 0% { transform:translate(-50%, -50%) rotate(90deg); }
- 100% { transform:translate(-50%, -50%) rotate(450deg); }
- }
- #_form_1_ ._close-icon { cursor:pointer; background-image:url('https://d226aj4ao1t61q.cloudfront.net/esfkyjh1u_forms-close-dark.png'); background-repeat:no-repeat; background-size:14.2px 14.2px; position:absolute; display:block; top:11px; right:9px; overflow:hidden; width:16.2px; height:16.2px; }
- #_form_1_ ._close-icon:before { position:relative; }
- //#_form_1_ ._form-body { margin-bottom:30px; }
- #_form_1_ ._form-image-left { width:150px; float:left; }
- #_form_1_ ._form-content-right { margin-left:164px; }
- #_form_1_ ._form-branding { color:#fff; font-size:10px; clear:both; text-align:left; margin-top:30px; font-weight:100; }
- #_form_1_ ._form-branding ._logo { display:block; width:130px; height:14px; margin-top:6px; background-image:url('https://d226aj4ao1t61q.cloudfront.net/hh9ujqgv5_aclogo_li.png'); background-size:130px auto; background-repeat:no-repeat; }
- #_form_1_ .form-sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0, 0, 0, 0); border:0; }
- #_form_1_ ._form-label,#_form_1_ ._form_element ._form-label { font-weight:bold; margin-bottom:5px; display:block; }
- #_form_1_._dark ._form-branding { color:#333; }
- #_form_1_._dark ._form-branding ._logo { background-image:url('https://d226aj4ao1t61q.cloudfront.net/jftq2c8s_aclogo_dk.png'); }
- #_form_1_ ._form_element { position:relative; margin-bottom:10px; font-size:0; max-width:100%; }
- #_form_1_ ._form_element * { font-size:14px; }
- #_form_1_ ._form_element._clear { clear:both; width:100%; float:none; }
- #_form_1_ ._form_element._clear:after { clear:left; }
- #_form_1_ ._form_element input[type="text"],#_form_1_ ._form_element input[type="date"],#_form_1_ ._form_element select,#_form_1_ ._form_element textarea:not(.g-recaptcha-response) { display:block; width:100%; -webkit-box-sizing:border-box; -moz-box-sizing:border-box; box-sizing:border-box; font-family:inherit; }
- #_form_1_ ._field-wrapper { position:relative; }
- #_form_1_ ._inline-style { float:left; }
- #_form_1_ ._inline-style input[type="text"] { width:150px; }
- #_form_1_ ._inline-style:not(._clear) + ._inline-style:not(._clear) { margin-left:20px; }
- #_form_1_ ._form_element img._form-image { max-width:100%; }
- #_form_1_ ._form_element ._form-fieldset { border:0; padding:0.01em 0 0 0; margin:0; min-width:0; }
- #_form_1_ ._clear-element { clear:left; }
- #_form_1_ ._full_width { width:100%; }
- #_form_1_ ._form_full_field { display:block; width:100%; margin-bottom:10px; }
- #_form_1_ input[type="text"]._has_error,#_form_1_ textarea._has_error { border:#f37c7b 1px solid; }
- #_form_1_ input[type="checkbox"]._has_error { outline:#f37c7b 1px solid; }
- #_form_1_ ._error { display:block; position:absolute; font-size:14px; z-index:10000001; }
- #_form_1_ ._error._above { padding-bottom:4px; bottom:39px; right:0; }
- #_form_1_ ._error._below { padding-top:8px; top:100%; right:0; }
- #_form_1_ ._error._above ._error-arrow { bottom:-4px; right:15px; border-left:8px solid transparent; border-right:8px solid transparent; border-top:8px solid #fdd; }
- #_form_1_ ._error._below ._error-arrow { top:0; right:15px; border-left:8px solid transparent; border-right:8px solid transparent; border-bottom:8px solid #fdd; }
- #_form_1_ ._error-inner { padding:12px 12px 12px 36px; background-color:#fdd; background-image:url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8ZM9 3V9H7V3H9ZM9 13V11H7V13H9Z' fill='%23CA0000'/%3E%3C/svg%3E"); background-repeat:no-repeat; background-position:12px center; font-size:14px; font-family:arial, sans-serif; font-weight:600; line-height:16px; color:#000; text-align:center; text-decoration:none; -webkit-border-radius:4px; -moz-border-radius:4px; border-radius:4px; box-shadow:0px 1px 4px rgba(31, 33, 41, 0.298295); }
- #_form_1_ ._error-inner._form_error { margin-bottom:5px; text-align:left; }
- #_form_1_ ._button-wrapper ._error-inner._form_error { position:static; }
- #_form_1_ ._error-inner._no_arrow { margin-bottom:10px; }
- #_form_1_ ._error-arrow { position:absolute; width:0; height:0; }
- #_form_1_ ._error-html { margin-bottom:10px; }
- .pika-single { z-index:10000001 !important; }
- #_form_1_ input[type="text"].datetime_date { width:69%; display:inline; }
- #_form_1_ select.datetime_time { width:29%; display:inline; height:32px; }
- #_form_1_ input[type="date"].datetime_date { width:69%; display:inline-flex; }
- #_form_1_ input[type="time"].datetime_time { width:29%; display:inline-flex; }
- @media all and (min-width:320px) and (max-width:667px) { ::-webkit-scrollbar { display:none; }
- #_form_1_ { margin:0; width:100%; min-width:100%; max-width:100%; box-sizing:border-box; }
- #_form_1_ * { -webkit-box-sizing:border-box; -moz-box-sizing:border-box; box-sizing:border-box; font-size:1em; }
- #_form_1_ ._form-content { margin:0; width:100%; }
- #_form_1_ ._form-inner { display:block; min-width:100%; }
- #_form_1_ ._form-title,#_form_1_ ._inline-style { margin-top:0; margin-right:0; margin-left:0; }
- #_form_1_ ._form-title { font-size:1.2em; }
- #_form_1_ ._form_element { margin:0 0 20px; padding:0; width:100%; }
- #_form_1_ ._form-element,#_form_1_ ._inline-style,#_form_1_ input[type="text"],#_form_1_ label,#_form_1_ p,#_form_1_ textarea:not(.g-recaptcha-response) { float:none; display:block; width:100%; }
- #_form_1_ ._row._checkbox-radio label { display:inline; }
- #_form_1_ ._row,#_form_1_ p,#_form_1_ label { margin-bottom:0.7em; width:100%; }
- #_form_1_ ._row input[type="checkbox"],#_form_1_ ._row input[type="radio"] { margin:0 !important; vertical-align:middle !important; }
- #_form_1_ ._row input[type="checkbox"] + span label { display:inline; }
- #_form_1_ ._row span label { margin:0 !important; width:initial !important; vertical-align:middle !important; }
- #_form_1_ ._form-image { max-width:100%; height:auto !important; }
- #_form_1_ input[type="text"] { padding-left:10px; padding-right:10px; font-size:16px; line-height:1.3em; -webkit-appearance:none; }
- #_form_1_ input[type="radio"],#_form_1_ input[type="checkbox"] { display:inline-block; width:1.3em; height:1.3em; font-size:1em; margin:0 0.3em 0 0; vertical-align:baseline; }
- #_form_1_ button[type="submit"] { padding:20px; font-size:1.5em; }
- #_form_1_ ._inline-style { margin:20px 0 0 !important; }
- }
- #_form_1_ { position:relative; text-align:left; margin:25px auto 0; padding-top:20px; padding-right:20px; padding-bottom:20px; padding-left:20px; -webkit-box-sizing:border-box; -moz-box-sizing:border-box; box-sizing:border-box; *zoom:1; background:#fff !important; border:0px solid #b0b0b0 !important; max-width:500px; -moz-border-radius:0px !important; -webkit-border-radius:0px !important; border-radius:0px !important; color:#000 !important; }
- #_form_1_._inline-form,#_form_1_._inline-form ._form-content,#_form_1_._inline-form input,#_form_1_._inline-form ._submit,#_form_1_._inline-form ._form-label,#_form_1_._inline-form ._html-code :not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) { font-family:"IBM Plex Sans", Helvetica, sans-serif; }
- #_form_1_._inline-form ._form-title { font-size:22px; line-height:normal; font-weight:600; margin-bottom:0; }
- #_form_1_:before,#_form_1_:after { content:" "; display:table; }
- #_form_1_:after { clear:both; }
- #_form_1_._inline-style { width:auto; display:inline-block; }
- #_form_1_._inline-style input[type="text"],#_form_1_._inline-style input[type="date"] { padding:10px 12px; }
- #_form_1_._inline-style button._inline-style { position:relative; top:27px; }
- #_form_1_._inline-style p { margin:0; }
- #_form_1_._inline-style ._button-wrapper { position:relative; margin:27px 12.5px 0 20px; }
- #_form_1_ ._form-thank-you { position:relative; left:0; right:0; text-align:center; font-size:18px; }
- @media all and (min-width:320px) and (max-width:667px) { #_form_1_._inline-form._inline-style ._inline-style._button-wrapper { margin-top:20px !important; margin-left:0 !important; }
- }
- #_form_1_ .iti.iti--allow-dropdown.iti--separate-dial-code { width:100%; }
- #_form_1_ .iti input { width:100%; height:32px; border:#979797 1px solid; border-radius:4px; }
- #_form_1_ .iti--separate-dial-code .iti__selected-flag { background-color:#fff; border-radius:4px; }
- #_form_1_ .iti--separate-dial-code .iti__selected-flag:hover { background-color:rgba(0, 0, 0, 0.05); }
- #_form_1_ .iti__country-list { border-radius:4px; margin-top:4px; min-width:460px; }
- #_form_1_ .iti__country-list--dropup { margin-bottom:4px; }
- #_form_1_ .phone-error-hidden { display:none; }
- #_form_1_ .phone-error { color:#e40e49; }
- #_form_1_ .phone-input-error { border:1px solid #e40e49 !important; }
-*/
-
-
- #_form_1_ { padding: 0; margin: 0;}
- #_form_1_ input { width: 100%; }
-
-
-
\ No newline at end of file
diff --git a/tests/phpunit/Admin/OptIn/EmailOptInTest.php b/tests/phpunit/Admin/OptIn/EmailOptInTest.php
new file mode 100644
index 00000000..adb7982f
--- /dev/null
+++ b/tests/phpunit/Admin/OptIn/EmailOptInTest.php
@@ -0,0 +1,223 @@
+current_user_id = $this->factory()->user->create();
+
+ if ( is_wp_error( $this->current_user_id ) ) {
+ $this->fail( $this->current_user_id->get_error_message() );
+ }
+
+ wp_set_current_user( $this->current_user_id );
+ }
+
+ /**
+ * Delete the user to clean up after tests.
+ */
+ protected function tearDown(): void {
+ wp_delete_user( $this->current_user_id );
+ }
+
+ /**
+ * Test that the user_already_subscribed method returns false when the user has not subscribed.
+ */
+ public function test_user_already_subscribed_returns_false_when_user_has_not_subscribed() {
+ $this->assertFalse( Email_Opt_In::user_already_subscribed() );
+ }
+
+ /**
+ * Test that the user_already_subscribed method returns true when the user has subscribed.
+ */
+ public function test_user_already_subscribed_returns_true_when_user_is_subscribed() {
+ update_user_meta( $this->current_user_id, Email_Opt_In::EDAC_USER_OPTIN_META_KEY, true );
+ $this->assertTrue( Email_Opt_In::user_already_subscribed() );
+ }
+
+ /**
+ * Test that the should_show_modal method returns true when the user has not seen the modal.
+ */
+ public function test_should_show_modal_returns_true_when_user_has_not_seen_it_yet() {
+ $this->assertTrue( Email_Opt_In::should_show_modal() );
+ }
+
+ /**
+ * Test that the should_show_modal method returns false when the user has seen the modal.
+ */
+ public function test_should_show_modal_returns_false_when_user_has_seen_it() {
+ update_user_meta( $this->current_user_id, Email_Opt_In::EDAC_USER_OPTIN_SEEN_MODAL_KEY, true );
+ $this->assertFalse( Email_Opt_In::should_show_modal() );
+ }
+
+ /**
+ * Test that the enqueue_scripts method registers the scripts and styles needed for the opt-in modal.
+ */
+ public function test_enqueue_scripts_registers_thickbox_when_user_has_not_seen_modal() {
+ $email_opt_in = new Email_Opt_In();
+ $email_opt_in->enqueue_scripts();
+ $this->assertTrue( wp_script_is( 'email-opt-in-form', 'enqueued' ) );
+ $this->assertTrue( wp_style_is( 'email-opt-in-form', 'enqueued' ) );
+ // check that admin footer has been hooked and thickbox is enqueued.
+ $this->assertEquals( 10, has_action( 'admin_footer', array( $email_opt_in, 'render_modal' ) ) );
+ $this->assertTrue( wp_script_is( 'thickbox', 'enqueued' ) );
+ }
+
+ /**
+ * Test that the enqueue_scripts method does not add thickbox when the user has seen the modal.
+ */
+ public function test_enqueue_scripts_does_not_add_thickbox_when_user_has_seen_modal() {
+ update_user_meta( $this->current_user_id, Email_Opt_In::EDAC_USER_OPTIN_SEEN_MODAL_KEY, true );
+ $email_opt_in = new Email_Opt_In();
+ $email_opt_in->enqueue_scripts();
+ $this->assertTrue( wp_script_is( 'email-opt-in-form', 'enqueued' ) );
+ $this->assertTrue( wp_style_is( 'email-opt-in-form', 'enqueued' ) );
+
+ // check that admin footer has NOT been hooked.
+ $this->assertFalse( has_action( 'admin_footer', array( $email_opt_in, 'render_modal' ) ) );
+ }
+
+ /**
+ * Test that the modal markup renders.
+ */
+ public function test_form_renders_modal() {
+ $email_opt_in = new Email_Opt_In();
+ $email_opt_in->render_modal();
+ $this->expectOutputRegex( '/ID, 'first_name', true ) ) {
+ update_user_meta( $maybe_existing_user->ID, 'first_name', self::TEST_USER_FIRST_NAME );
+ }
+
+ $user_id = $maybe_existing_user ? $maybe_existing_user->ID : $this->factory()->user->create(
+ array(
+ 'user_email' => self::TEST_USER_EMAIL,
+ 'first_name' => self::TEST_USER_FIRST_NAME,
+ )
+ );
+ wp_set_current_user( $user_id );
+ $email_opt_in = new Email_Opt_In();
+ $email_opt_in->render_form();
+ $this->expectOutputRegex( '/.*?value="' . self::TEST_USER_EMAIL . '".*?/' );
+ $this->expectOutputRegex( '/.*?value="' . self::TEST_USER_FIRST_NAME . '".*?/' );
+ }
+
+ /**
+ * Test that the ajax handlers are registered.
+ */
+ public function test_ajax_handlers_registered() {
+ $email_opt_in = new Email_Opt_In();
+ $email_opt_in->register_ajax_handlers();
+ $this->assertEquals( 10, has_action( 'wp_ajax_edac_email_opt_in_ajax', array( $email_opt_in, 'handle_email_opt_in' ) ) );
+ $this->assertEquals( 10, has_action( 'wp_ajax_edac_email_opt_in_closed_modal_ajax', array( $email_opt_in, 'handle_email_opt_in_closed_modal' ) ) );
+ }
+
+ /**
+ * Test that the email opt-in ajax handler creates the user meta.
+ */
+ public function test_handle_email_opt_in() {
+ // mock the action in the $_POST global.
+ $_POST['action'] = 'edac_email_opt_in_ajax';
+ $email_opt_in = new Email_Opt_In();
+
+ $this->filter_ajax_die_handler_to_exception_instead_of_actual_die();
+ try {
+ ob_start();
+ $email_opt_in->handle_email_opt_in();
+ } catch ( Exception $e ) {
+ // We expected this, just clear the buffer.
+ ob_end_clean();
+ }
+
+ $this->assertTrue(
+ (bool) get_user_meta(
+ get_current_user_id(),
+ Email_Opt_In::EDAC_USER_OPTIN_META_KEY,
+ true
+ )
+ );
+ }
+
+ /**
+ * Test that the email opt-in closed modal ajax handler creates the user meta.
+ */
+ public function test_handle_email_opt_in_closed_modal() {
+ // mock the action in the $_POST global.
+ $_POST['action'] = 'handle_email_opt_in_closed_modal_ajax';
+ $email_opt_in = new Email_Opt_In();
+
+ $this->filter_ajax_die_handler_to_exception_instead_of_actual_die();
+ try {
+ ob_start();
+ $email_opt_in->handle_email_opt_in_closed_modal();
+ } catch ( Exception $e ) {
+ // We expected this, just clear the buffer.
+ ob_end_clean();
+ }
+
+ $this->assertTrue(
+ (bool) get_user_meta(
+ get_current_user_id(),
+ Email_Opt_In::EDAC_USER_OPTIN_SEEN_MODAL_KEY,
+ true
+ )
+ );
+ }
+
+ /**
+ * Filter the wp_die handler to throw an exception instead of actually dying,
+ * so that we can test the ajax handlers.
+ */
+ private function filter_ajax_die_handler_to_exception_instead_of_actual_die() {
+ add_filter( 'wp_doing_ajax', '__return_true' );
+ add_filter(
+ 'wp_die_ajax_handler',
+ array( $this, 'throw_exception_instead_of_dying' ),
+ 1,
+ 1
+ );
+ }
+
+ /**
+ * Throw an exception instead of actually dying.
+ *
+ * @return Closure
+ */
+ public function throw_exception_instead_of_dying() {
+ return function ( $message ) {
+ // phpcs:ignore WordPress.Security -- this is just a test.
+ throw new Exception( $message );
+ };
+ }
+}
diff --git a/tests/phpunit/helper-functions/UrlExistsTest.php b/tests/phpunit/helper-functions/UrlExistsTest.php
index e2bda1a1..a6e9c9ad 100644
--- a/tests/phpunit/helper-functions/UrlExistsTest.php
+++ b/tests/phpunit/helper-functions/UrlExistsTest.php
@@ -17,7 +17,7 @@ class UrlExistsTest extends WP_UnitTestCase {
*/
public function test_url_exists() {
$url = 'https://httpbin.org/status/200';
- $this->assertTrue( edac_url_exists( $url ) );
+ $this->assertTrue( edac_url_exists( $url, 20 ) );
}
/**