<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[54722] trunk/tests/phpunit/tests/ajax: Tests: Rename classes in `phpunit/tests/ajax/` per the naming conventions.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/54722">54722</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/54722","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>SergeyBiryukov</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2022-10-30 01:05:06 +0000 (Sun, 30 Oct 2022)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Tests: Rename classes in `phpunit/tests/ajax/` per the naming conventions.
This updates the test classes to match the names of the functions being tested.
Includes moving the `@covers` tags from individual test methods to the class DocBlocks.
Reference: [https://make.wordpress.org/core/handbook/testing/automated-testing/writing-phpunit-tests/#naming-and-organization Writing PHP Tests: Naming and Organization].
Follow-up to <a href="https://core.trac.wordpress.org/changeset/47780">[47780]</a>, <a href="https://core.trac.wordpress.org/changeset/48911">[48911]</a>, <a href="https://core.trac.wordpress.org/changeset/49327">[49327]</a>, <a href="https://core.trac.wordpress.org/changeset/50291">[50291]</a>, <a href="https://core.trac.wordpress.org/changeset/50292">[50292]</a>, <a href="https://core.trac.wordpress.org/changeset/50342">[50342]</a>, <a href="https://core.trac.wordpress.org/changeset/50452">[50452]</a>, <a href="https://core.trac.wordpress.org/changeset/50453">[50453]</a>, <a href="https://core.trac.wordpress.org/changeset/50456">[50456]</a>, <a href="https://core.trac.wordpress.org/changeset/50967">[50967]</a>, <a href="https://core.trac.wordpress.org/changeset/50968">[50968]</a>, <a href="https://core.trac.wordpress.org/changeset/50969">[50969]</a>, <a href="https://core.trac.wordpress.org/changeset/51491">[51491]</a>, <a href="https://core.trac.wordpress.org/changeset/51492">[514
92]</a>, <a href="https://core.trac.wordpress.org/changeset/51493">[51493]</a>, <a href="https://core.trac.wordpress.org/changeset/51623">[51623]</a>, <a href="https://core.trac.wordpress.org/changeset/51639">[51639]</a>, <a href="https://core.trac.wordpress.org/changeset/51646">[51646]</a>, <a href="https://core.trac.wordpress.org/changeset/51650">[51650]</a>, <a href="https://core.trac.wordpress.org/changeset/51651">[51651]</a>, <a href="https://core.trac.wordpress.org/changeset/51860">[51860]</a>, <a href="https://core.trac.wordpress.org/changeset/52264">[52264]</a>, <a href="https://core.trac.wordpress.org/changeset/52265">[52265]</a>, <a href="https://core.trac.wordpress.org/changeset/53489">[53489]</a>, <a href="https://core.trac.wordpress.org/changeset/53561">[53561]</a>, <a href="https://core.trac.wordpress.org/changeset/54704">[54704]</a>.
See <a href="https://core.trac.wordpress.org/ticket/56793">#56793</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunktestsphpunittestsajaxwpAjaxCropImagephp">trunk/tests/phpunit/tests/ajax/wpAjaxCropImage.php</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunktestsphpunittestsajaxwpAjaxAddMetaphp">trunk/tests/phpunit/tests/ajax/wpAjaxAddMeta.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxAddTagphp">trunk/tests/phpunit/tests/ajax/wpAjaxAddTag.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxAjaxTagSearchphp">trunk/tests/phpunit/tests/ajax/wpAjaxAjaxTagSearch.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxDeleteCommentphp">trunk/tests/phpunit/tests/ajax/wpAjaxDeleteComment.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxDeletePluginphp">trunk/tests/phpunit/tests/ajax/wpAjaxDeletePlugin.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxDimCommentphp">trunk/tests/phpunit/tests/ajax/wpAjaxDimComment.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxEditCommentphp">trunk/tests/phpunit/tests/ajax/wpAjaxEditComment.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxGetCommentsphp">trunk/tests/phpunit/tests/ajax/wpAjaxGetComments.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxHeartbeatphp">trunk/tests/phpunit/tests/ajax/wpAjaxHeartbeat.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxImageEditorphp">trunk/tests/phpunit/tests/ajax/wpAjaxImageEditor.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxInlineSavephp">trunk/tests/phpunit/tests/ajax/wpAjaxInlineSave.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxReplytoCommentphp">trunk/tests/phpunit/tests/ajax/wpAjaxReplytoComment.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxResponsephp">trunk/tests/phpunit/tests/ajax/wpAjaxResponse.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxSendAttachmentToEditorphp">trunk/tests/phpunit/tests/ajax/wpAjaxSendAttachmentToEditor.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxUpdatePluginphp">trunk/tests/phpunit/tests/ajax/wpAjaxUpdatePlugin.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxUpdateThemephp">trunk/tests/phpunit/tests/ajax/wpAjaxUpdateTheme.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxWpCompressionTestphp">trunk/tests/phpunit/tests/ajax/wpAjaxWpCompressionTest.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxWpPrivacyErasePersonalDataphp">trunk/tests/phpunit/tests/ajax/wpAjaxWpPrivacyErasePersonalData.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpAjaxWpPrivacyExportPersonalDataphp">trunk/tests/phpunit/tests/ajax/wpAjaxWpPrivacyExportPersonalData.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpCustomizeManagerphp">trunk/tests/phpunit/tests/ajax/wpCustomizeManager.php</a></li>
<li><a href="#trunktestsphpunittestsajaxwpCustomizeNavMenusphp">trunk/tests/phpunit/tests/ajax/wpCustomizeNavMenus.php</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#trunktestsphpunittestsajaxAddMetaphp">trunk/tests/phpunit/tests/ajax/AddMeta.php</a></li>
<li><a href="#trunktestsphpunittestsajaxAddTagphp">trunk/tests/phpunit/tests/ajax/AddTag.php</a></li>
<li><a href="#trunktestsphpunittestsajaxAttachmentsphp">trunk/tests/phpunit/tests/ajax/Attachments.php</a></li>
<li><a href="#trunktestsphpunittestsajaxAutosavephp">trunk/tests/phpunit/tests/ajax/Autosave.php</a></li>
<li><a href="#trunktestsphpunittestsajaxCompressionphp">trunk/tests/phpunit/tests/ajax/Compression.php</a></li>
<li><a href="#trunktestsphpunittestsajaxCustomizeManagerphp">trunk/tests/phpunit/tests/ajax/CustomizeManager.php</a></li>
<li><a href="#trunktestsphpunittestsajaxCustomizeMenusphp">trunk/tests/phpunit/tests/ajax/CustomizeMenus.php</a></li>
<li><a href="#trunktestsphpunittestsajaxDeleteCommentphp">trunk/tests/phpunit/tests/ajax/DeleteComment.php</a></li>
<li><a href="#trunktestsphpunittestsajaxDeletePluginphp">trunk/tests/phpunit/tests/ajax/DeletePlugin.php</a></li>
<li><a href="#trunktestsphpunittestsajaxDimCommentphp">trunk/tests/phpunit/tests/ajax/DimComment.php</a></li>
<li><a href="#trunktestsphpunittestsajaxEditCommentphp">trunk/tests/phpunit/tests/ajax/EditComment.php</a></li>
<li><a href="#trunktestsphpunittestsajaxGetCommentsphp">trunk/tests/phpunit/tests/ajax/GetComments.php</a></li>
<li><a href="#trunktestsphpunittestsajaxManageThemesphp">trunk/tests/phpunit/tests/ajax/ManageThemes.php</a></li>
<li><a href="#trunktestsphpunittestsajaxMediaEditphp">trunk/tests/phpunit/tests/ajax/MediaEdit.php</a></li>
<li><a href="#trunktestsphpunittestsajaxPrivacyErasePersonalDataphp">trunk/tests/phpunit/tests/ajax/PrivacyErasePersonalData.php</a></li>
<li><a href="#trunktestsphpunittestsajaxPrivacyExportPersonalDataphp">trunk/tests/phpunit/tests/ajax/PrivacyExportPersonalData.php</a></li>
<li><a href="#trunktestsphpunittestsajaxQuickEditphp">trunk/tests/phpunit/tests/ajax/QuickEdit.php</a></li>
<li><a href="#trunktestsphpunittestsajaxReplytoCommentphp">trunk/tests/phpunit/tests/ajax/ReplytoComment.php</a></li>
<li><a href="#trunktestsphpunittestsajaxResponsephp">trunk/tests/phpunit/tests/ajax/Response.php</a></li>
<li><a href="#trunktestsphpunittestsajaxTagSearchphp">trunk/tests/phpunit/tests/ajax/TagSearch.php</a></li>
<li><a href="#trunktestsphpunittestsajaxUpdatePluginphp">trunk/tests/phpunit/tests/ajax/UpdatePlugin.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunktestsphpunittestsajaxAddMetaphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/AddMeta.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/AddMeta.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/AddMeta.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,77 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Add Meta AJAX functionality.
- *
- * @group ajax
- */
-class Tests_Ajax_AddMeta extends WP_Ajax_UnitTestCase {
- /**
- * @ticket 43559
- *
- * @covers ::wp_ajax_add_meta
- * @covers ::add_post_meta
- */
- public function test_wp_ajax_add_meta_allows_empty_values_on_adding() {
- $post = self::factory()->post->create();
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- $_POST = array(
- 'post_id' => $post,
- 'metakeyinput' => 'testkey',
- 'metavalue' => '',
- '_ajax_nonce-add-meta' => wp_create_nonce( 'add-meta' ),
- );
-
- // Make the request.
- try {
- $this->_handleAjax( 'add-meta' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- $this->assertSame( '', get_post_meta( $post, 'testkey', true ) );
- }
-
- /**
- * @ticket 43559
- *
- * @covers ::wp_ajax_add_meta
- * @covers ::update_metadata_by_mid
- */
- public function test_wp_ajax_add_meta_allows_empty_values_on_updating() {
- $post = self::factory()->post->create();
-
- $meta_id = add_post_meta( $post, 'testkey', 'hello' );
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- $_POST = array(
- '_ajax_nonce-add-meta' => wp_create_nonce( 'add-meta' ),
- 'post_id' => $post,
- 'meta' => array(
- $meta_id => array(
- 'key' => 'testkey',
- 'value' => '',
- ),
- ),
- );
-
- // Make the request.
- try {
- $this->_handleAjax( 'add-meta' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- $this->assertSame( '', get_post_meta( $post, 'testkey', true ) );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxAddTagphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/AddTag.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/AddTag.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/AddTag.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,156 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-/**
- * Admin ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Class for testing ajax add tag functionality.
- *
- * @group ajax
- */
-class Tests_Ajax_AddTag extends WP_Ajax_UnitTestCase {
-
- /**
- * @dataProvider data_add_tag
- *
- * @ticket 42937
- *
- * @covers ::wp_ajax_add_tag
- * @covers ::wp_insert_term
- *
- * @param array $post_data Data to populate $_POST.
- * @param string $expected Expected response.
- * @param array|string|callable $callback Optional. Callback to register to 'term_updated_messages'
- * filter. Default empty string (no callback).
- */
- public function test_add_tag( array $post_data, $expected, $callback = '' ) {
- $this->_setRole( 'administrator' );
-
- $_POST = $post_data;
- $_POST['_wpnonce_add-tag'] = wp_create_nonce( 'add-tag' );
-
- if ( ! empty( $callback ) ) {
- add_filter( 'term_updated_messages', $callback );
- }
-
- try {
- $this->_handleAjax( 'add-tag' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // The response message is in the `data` property in WP 5.9.
- $this->assertSame( $expected, (string) $this->get_xml_response_taxonomy()->response_data );
- // The response message is in the `supplemental->notice` property in WP 6.0+.
- $this->assertSame( $expected, (string) $this->get_xml_response_taxonomy()->supplemental->notice );
- }
-
- /**
- * Data provider.
- *
- * @return array
- */
- public function data_add_tag() {
- return array(
- 'add a category' => array(
- 'post_data' => array(
- 'taxonomy' => 'category',
- 'post_type' => 'post',
- 'screen' => 'edit-category',
- 'action' => 'add-tag',
- 'tag-name' => 'blues',
- ),
- 'expected' => 'Category added.',
- ),
- 'add a category with message filtering' => array(
- 'post_data' => array(
- 'taxonomy' => 'category',
- 'post_type' => 'post',
- 'screen' => 'edit-category',
- 'action' => 'add-tag',
- 'tag-name' => 'techno',
- ),
- 'expected' => 'A new category added.',
- 'callback' => static function( array $messages ) {
- $messages['category'][1] = 'A new category added.';
- return $messages;
- },
- ),
- 'add a post_tag' => array(
- 'post_data' => array(
- 'taxonomy' => 'post_tag',
- 'post_type' => 'post',
- 'screen' => 'edit-post_tag',
- 'action' => 'add-tag',
- 'tag-name' => 'Louis Armstrong',
- ),
- 'expected' => 'Tag added.',
- ),
- );
- }
-
- /**
- * @ticket 42937
- *
- * @covers ::wp_ajax_add_tag
- */
- public function test_adding_category_without_capability_should_error() {
- $this->_setRole( 'subscriber' );
-
- $_POST['taxonomy'] = 'category';
- $_POST['post_type'] = 'post';
- $_POST['screen'] = 'edit-category';
- $_POST['action'] = 'add-tag';
- $_POST['tag - name'] = 'disco';
- $_POST['_wpnonce_add-tag'] = wp_create_nonce( 'add-tag' );
-
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'add-tag' );
- }
-
- /**
- * @ticket 42937
- *
- * @covers ::wp_ajax_add_tag
- * @covers ::wp_insert_term
- */
- public function test_adding_existing_category_should_error() {
- $this->_setRole( 'administrator' );
-
- wp_insert_term( 'testcat', 'category' );
-
- $_POST = array(
- 'taxonomy' => 'category',
- 'post_type' => 'post',
- 'screen' => 'edit-category',
- 'action' => 'add-tag',
- 'tag-name' => 'testcat',
- '_wpnonce_add-tag' => wp_create_nonce( 'add-tag' ),
- );
-
- try {
- $this->_handleAjax( 'add-tag' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- $expected = 'A term with the name provided already exists with this parent.';
- $this->assertSame( $expected, (string) $this->get_xml_response_taxonomy()->wp_error );
- }
-
- /**
- * Helper method to get the taxonomy's response or error.
- *
- * @since 5.9.0
- *
- * @return SimpleXMLElement Response or error object.
- */
- private function get_xml_response_taxonomy() {
- $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
-
- return $xml->response->taxonomy;
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxAttachmentsphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/Attachments.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/Attachments.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/Attachments.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,104 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Ajax attachment handling.
- *
- * @group ajax
- */
-class Tests_Ajax_Attachments extends WP_Ajax_UnitTestCase {
- /**
- * @ticket 36578
- *
- * @covers ::wp_ajax_send_attachment_to_editor
- * @covers ::get_image_send_to_editor
- */
- public function test_wp_ajax_send_attachment_to_editor_should_return_an_image() {
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- $filename = DIR_TESTDATA . '/images/canola.jpg';
- $contents = file_get_contents( $filename );
-
- $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
- $attachment = $this->_make_attachment( $upload );
-
- // Set up a default request.
- $_POST['nonce'] = wp_create_nonce( 'media-send-to-editor' );
- $_POST['html'] = 'Bar Baz';
- $_POST['post_id'] = 0;
- $_POST['attachment'] = array(
- 'id' => $attachment,
- 'align' => 'left',
- 'image-size' => 'large',
- 'image_alt' => 'Foo bar',
- 'url' => 'http://example.com/',
- );
-
- // Make the request.
- try {
- $this->_handleAjax( 'send-attachment-to-editor' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = get_image_send_to_editor( $attachment, '', '', 'left', 'http://example.com/', false, 'large', 'Foo bar' );
-
- // Ensure everything is correct.
- $this->assertTrue( $response['success'] );
- $this->assertSame( $expected, $response['data'] );
- }
-
- /**
- * @ticket 36578
- * @group ms-excluded
- *
- * @covers ::wp_ajax_send_attachment_to_editor
- */
- public function test_wp_ajax_send_attachment_to_editor_should_return_a_link() {
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- $filename = DIR_TESTDATA . '/formatting/entities.txt';
- $contents = file_get_contents( $filename );
-
- $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
- $attachment = $this->_make_attachment( $upload );
-
- // Set up a default request.
- $_POST['nonce'] = wp_create_nonce( 'media-send-to-editor' );
- $_POST['html'] = 'Bar Baz';
- $_POST['post_id'] = 0;
- $_POST['attachment'] = array(
- 'id' => $attachment,
- 'post_title' => 'Foo bar',
- 'url' => get_attachment_link( $attachment ),
- );
-
- // Make the request.
- try {
- $this->_handleAjax( 'send-attachment-to-editor' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = sprintf(
- '<a href="%s" rel="attachment wp-att-%d">Foo bar</a>',
- get_attachment_link( $attachment ),
- $attachment
- );
-
- // Ensure everything is correct.
- $this->assertTrue( $response['success'] );
- $this->assertSame( $expected, $response['data'] );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxAutosavephp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/Autosave.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/Autosave.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/Autosave.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,170 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Ajax save draft functionality.
- *
- * @package WordPress
- * @subpackage UnitTests
- * @since 3.4.0
- * @group ajax
- */
-class Tests_Ajax_Autosave extends WP_Ajax_UnitTestCase {
-
- /**
- * Post
- *
- * @var mixed
- */
- protected $_post = null;
-
- protected static $admin_id = 0;
- protected static $editor_id = 0;
- protected static $post;
- protected static $post_id;
-
- public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
- self::$admin_id = $factory->user->create( array( 'role' => 'administrator' ) );
- self::$editor_id = $factory->user->create( array( 'role' => 'editor' ) );
-
- // Set a user so the $post has 'post_author'.
- wp_set_current_user( self::$admin_id );
-
- self::$post_id = $factory->post->create( array( 'post_status' => 'draft' ) );
- self::$post = get_post( self::$post_id );
- }
-
- /**
- * Tests autosaving a post.
- *
- * @covers ::wp_ajax_heartbeat
- */
- public function test_autosave_post() {
- // The original post_author.
- wp_set_current_user( self::$admin_id );
-
- // Set up the $_POST request.
- $md5 = md5( uniqid() );
- $_POST = array(
- 'action' => 'heartbeat',
- '_nonce' => wp_create_nonce( 'heartbeat-nonce' ),
- 'data' => array(
- 'wp_autosave' => array(
- 'post_id' => self::$post_id,
- '_wpnonce' => wp_create_nonce( 'update-post_' . self::$post_id ),
- 'post_content' => self::$post->post_content . PHP_EOL . $md5,
- 'post_type' => 'post',
- ),
- ),
- );
-
- // Make the request.
- try {
- $this->_handleAjax( 'heartbeat' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response, it is in heartbeat's response.
- $response = json_decode( $this->_last_response, true );
-
- // Ensure everything is correct.
- $this->assertNotEmpty( $response['wp_autosave'] );
- $this->assertTrue( $response['wp_autosave']['success'] );
-
- // Check that the edit happened.
- $post = get_post( self::$post_id );
- $this->assertStringContainsString( $md5, $post->post_content );
- }
-
- /**
- * Tests autosaving a locked post.
- *
- * @covers ::wp_ajax_heartbeat
- */
- public function test_autosave_locked_post() {
- // Lock the post to another user.
- wp_set_current_user( self::$editor_id );
- wp_set_post_lock( self::$post_id );
-
- wp_set_current_user( self::$admin_id );
-
- // Ensure post is locked.
- $this->assertEquals( self::$editor_id, wp_check_post_lock( self::$post_id ) );
-
- // Set up the $_POST request.
- $md5 = md5( uniqid() );
- $_POST = array(
- 'action' => 'heartbeat',
- '_nonce' => wp_create_nonce( 'heartbeat-nonce' ),
- 'data' => array(
- 'wp_autosave' => array(
- 'post_id' => self::$post_id,
- '_wpnonce' => wp_create_nonce( 'update-post_' . self::$post_id ),
- 'post_content' => self::$post->post_content . PHP_EOL . $md5,
- 'post_type' => 'post',
- ),
- ),
- );
-
- // Make the request.
- try {
- $this->_handleAjax( 'heartbeat' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- $response = json_decode( $this->_last_response, true );
-
- // Ensure everything is correct.
- $this->assertNotEmpty( $response['wp_autosave'] );
- $this->assertTrue( $response['wp_autosave']['success'] );
-
- // Check that the original post was NOT edited.
- $post = get_post( self::$post_id );
- $this->assertStringNotContainsString( $md5, $post->post_content );
-
- // Check if the autosave post was created.
- $autosave = wp_get_post_autosave( self::$post_id, get_current_user_id() );
- $this->assertNotEmpty( $autosave );
- $this->assertStringContainsString( $md5, $autosave->post_content );
- }
-
- /**
- * Tests with an invalid nonce.
- *
- * @covers ::wp_ajax_heartbeat
- */
- public function test_with_invalid_nonce() {
-
- wp_set_current_user( self::$admin_id );
-
- // Set up the $_POST request.
- $_POST = array(
- 'action' => 'heartbeat',
- '_nonce' => wp_create_nonce( 'heartbeat-nonce' ),
- 'data' => array(
- 'wp_autosave' => array(
- 'post_id' => self::$post_id,
- '_wpnonce' => substr( md5( uniqid() ), 0, 10 ),
- ),
- ),
- );
-
- // Make the request.
- try {
- $this->_handleAjax( 'heartbeat' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- $response = json_decode( $this->_last_response, true );
-
- $this->assertNotEmpty( $response['wp_autosave'] );
- $this->assertFalse( $response['wp_autosave']['success'] );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxCompressionphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/Compression.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/Compression.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/Compression.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,236 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Ajax compression test functionality.
- *
- * @package WordPress
- * @subpackage UnitTests
- * @since 3.4.0
- * @group ajax
- */
-class Tests_Ajax_CompressionTest extends WP_Ajax_UnitTestCase {
-
- /**
- * Test as a logged out user
- *
- * @covers ::wp_ajax_wp_compression_test
- */
- public function test_logged_out() {
- $this->logout();
-
- // Set up a default request.
- $_GET['test'] = 1;
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'wp-compression-test' );
- }
-
- /**
- * Fetch the test text
- *
- * @covers ::wp_ajax_wp_compression_test
- */
- public function test_text() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_GET['test'] = 1;
-
- // Make the request.
- try {
- $this->_handleAjax( 'wp-compression-test' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Ensure we found the right match.
- $this->assertStringContainsString( 'wpCompressionTest', $this->_last_response );
- }
-
- /**
- * Fetch the test text (gzdeflate)
- *
- * @requires function gzdeflate
- *
- * @covers ::wp_ajax_wp_compression_test
- */
- public function test_gzdeflate() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_GET['test'] = 2;
- $_SERVER['HTTP_ACCEPT_ENCODING'] = 'deflate';
-
- // Make the request.
- try {
- $this->_handleAjax( 'wp-compression-test' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Ensure we found the right match.
- $this->assertStringContainsString( 'wpCompressionTest', gzinflate( $this->_last_response ) );
- }
-
- /**
- * Fetch the test text (gzencode)
- *
- * @requires function gzencode
- *
- * @covers ::wp_ajax_wp_compression_test
- */
- public function test_gzencode() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_GET['test'] = 2;
- $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip';
-
- // Make the request.
- try {
- $this->_handleAjax( 'wp-compression-test' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Ensure we found the right match.
- $this->assertStringContainsString( 'wpCompressionTest', $this->_gzdecode( $this->_last_response ) );
- }
-
- /**
- * Fetch the test text (unknown encoding)
- *
- * @covers ::wp_ajax_wp_compression_test
- */
- public function test_unknown_encoding() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_GET['test'] = 2;
- $_SERVER['HTTP_ACCEPT_ENCODING'] = 'unknown';
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'wp-compression-test' );
- }
-
- /**
- * Set the 'can_compress_scripts' site option to true
- *
- * @covers ::wp_ajax_wp_compression_test
- */
- public function test_set_yes() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_GET['test'] = 'yes';
-
- // Set the option to false.
- update_site_option( 'can_compress_scripts', 0 );
-
- // Make the request.
- try {
- $this->_handleAjax( 'wp-compression-test' );
- } catch ( WPAjaxDieStopException $e ) {
- unset( $e );
- }
-
- // Check the site option is not changed due to lack of nonce.
- $this->assertSame( 0, get_site_option( 'can_compress_scripts' ) );
-
- // Add a nonce.
- $_GET['_ajax_nonce'] = wp_create_nonce( 'update_can_compress_scripts' );
-
- // Retry the request.
- try {
- $this->_handleAjax( 'wp-compression-test' );
- } catch ( WPAjaxDieStopException $e ) {
- unset( $e );
- }
-
- // Check the site option is changed.
- $this->assertSame( 1, get_site_option( 'can_compress_scripts' ) );
- }
-
- /**
- * Set the 'can_compress_scripts' site option to false
- *
- * @covers ::wp_ajax_wp_compression_test
- */
- public function test_set_no() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_GET['test'] = 'no';
-
- // Set the option to true.
- update_site_option( 'can_compress_scripts', 1 );
-
- // Make the request.
- try {
- $this->_handleAjax( 'wp-compression-test' );
- } catch ( WPAjaxDieStopException $e ) {
- unset( $e );
- }
-
- // Check the site option is not changed due to lack of nonce.
- $this->assertSame( 1, get_site_option( 'can_compress_scripts' ) );
-
- // Add a nonce.
- $_GET['_ajax_nonce'] = wp_create_nonce( 'update_can_compress_scripts' );
-
- // Retry the request.
- try {
- $this->_handleAjax( 'wp-compression-test' );
- } catch ( WPAjaxDieStopException $e ) {
- unset( $e );
- }
-
- // Check the site option is changed.
- $this->assertSame( 0, get_site_option( 'can_compress_scripts' ) );
- }
-
- /**
- * Undo gzencode. This is ugly, but there's no stock gzdecode() function.
- *
- * @param string $encoded_data
- * @return string
- */
- protected function _gzdecode( $encoded_data ) {
-
- // Save the encoded data to a temp file.
- $file = wp_tempnam( 'gzdecode' );
- file_put_contents( $file, $encoded_data );
-
- // Flush it to the output buffer and delete the temp file.
- ob_start();
- readgzfile( $file );
- unlink( $file );
-
- // Save the data stop buffering.
- $data = ob_get_clean();
-
- // Done.
- return $data;
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxCustomizeManagerphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/CustomizeManager.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/CustomizeManager.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/CustomizeManager.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,768 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Testing Ajax customize manager functionality.
- *
- * @package WordPress
- * @subpackage UnitTests
- * @since 4.3.0
- * @group ajax
- */
-class Tests_Ajax_CustomizeManager extends WP_Ajax_UnitTestCase {
-
- /**
- * Instance of WP_Customize_Manager which is reset for each test.
- *
- * @var WP_Customize_Manager
- */
- public $wp_customize;
-
- /**
- * Admin user ID.
- *
- * @var int
- */
- protected static $admin_user_id;
-
- /**
- * Subscriber user ID.
- *
- * @var int
- */
- protected static $subscriber_user_id;
-
- /**
- * Last response parsed.
- *
- * @var array|null
- */
- protected $_last_response_parsed;
-
- /**
- * Set up before class.
- *
- * @param WP_UnitTest_Factory $factory Factory.
- */
- public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
- self::$subscriber_user_id = $factory->user->create( array( 'role' => 'subscriber' ) );
- self::$admin_user_id = $factory->user->create( array( 'role' => 'administrator' ) );
- }
-
- /**
- * Set up the test fixture.
- */
- public function set_up() {
- parent::set_up();
- require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
- }
-
- /**
- * Tear down.
- */
- public function tear_down() {
- $_REQUEST = array();
- parent::tear_down();
- }
-
- /**
- * Helper to keep it DRY
- *
- * @param string $action Action.
- */
- protected function make_ajax_call( $action ) {
- $this->_last_response_parsed = null;
- $this->_last_response = '';
- try {
- $this->_handleAjax( $action );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
- if ( $this->_last_response ) {
- $this->_last_response_parsed = json_decode( $this->_last_response, true );
- }
- }
-
- /**
- * Overridden caps for user_has_cap.
- *
- * @var array
- */
- protected $overridden_caps = array();
-
- /**
- * Dynamically filter a user's capabilities.
- *
- * @param array $allcaps An array of all the user's capabilities.
- * @return array All caps.
- */
- public function filter_user_has_cap( $allcaps ) {
- $allcaps = array_merge( $allcaps, $this->overridden_caps );
- return $allcaps;
- }
-
- /**
- * Test WP_Customize_Manager::save().
- *
- * @ticket 30937
- *
- * @covers WP_Customize_Manager::save
- */
- public function test_save_failures() {
- global $wp_customize;
- $wp_customize = new WP_Customize_Manager();
- $wp_customize->register_controls();
- add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ) );
-
- // Unauthenticated.
- wp_set_current_user( 0 );
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'unauthenticated', $this->_last_response_parsed['data'] );
-
- // Unauthorized.
- wp_set_current_user( self::$subscriber_user_id );
- $nonce = wp_create_nonce( 'save-customize_' . $wp_customize->get_stylesheet() );
- $_POST['nonce'] = $nonce;
- $_GET['nonce'] = $nonce;
- $_REQUEST['nonce'] = $nonce;
- $exception = null;
- try {
- ob_start();
- $wp_customize->setup_theme();
- } catch ( WPAjaxDieContinueException $e ) {
- $exception = $e;
- }
- $this->assertNotEmpty( $e );
- $this->assertSame( '-1', $e->getMessage() );
-
- // Not called setup_theme.
- wp_set_current_user( self::$admin_user_id );
- $nonce = wp_create_nonce( 'save-customize_' . $wp_customize->get_stylesheet() );
- $_POST['nonce'] = $nonce;
- $_GET['nonce'] = $nonce;
- $_REQUEST['nonce'] = $nonce;
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'not_preview', $this->_last_response_parsed['data'] );
-
- // Bad nonce.
- $_POST['nonce'] = 'bad';
- $_GET['nonce'] = 'bad';
- $_REQUEST['nonce'] = 'bad';
- $wp_customize->setup_theme();
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'invalid_nonce', $this->_last_response_parsed['data'] );
-
- // User cannot create.
- $nonce = wp_create_nonce( 'save-customize_' . $wp_customize->get_stylesheet() );
- $_POST['nonce'] = $nonce;
- $_GET['nonce'] = $nonce;
- $_REQUEST['nonce'] = $nonce;
- $post_type_obj = get_post_type_object( 'customize_changeset' );
- $post_type_obj->cap->create_posts = 'create_customize_changesets';
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'cannot_create_changeset_post', $this->_last_response_parsed['data'] );
- $this->overridden_caps[ $post_type_obj->cap->create_posts ] = true;
- $this->make_ajax_call( 'customize_save' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $post_type_obj->cap->create_posts = 'customize'; // Restore.
-
- // Changeset already published.
- $wp_customize->set_post_value( 'blogname', 'Hello' );
- $wp_customize->save_changeset_post( array( 'status' => 'publish' ) );
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'changeset_already_published', $this->_last_response_parsed['data']['code'] );
- wp_update_post(
- array(
- 'ID' => $wp_customize->changeset_post_id(),
- 'post_status' => 'auto-draft',
- )
- );
-
- // User cannot edit.
- $post_type_obj = get_post_type_object( 'customize_changeset' );
- $post_type_obj->cap->edit_post = 'edit_customize_changesets';
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'cannot_edit_changeset_post', $this->_last_response_parsed['data'] );
- $this->overridden_caps[ $post_type_obj->cap->edit_post ] = true;
- $this->make_ajax_call( 'customize_save' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $post_type_obj->cap->edit_post = 'customize'; // Restore.
-
- // Bad customize_changeset_data.
- $_POST['customize_changeset_data'] = '[MALFORMED]';
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'invalid_customize_changeset_data', $this->_last_response_parsed['data'] );
-
- // Bad customize_changeset_status.
- $_POST['customize_changeset_data'] = '{}';
- $_POST['customize_changeset_status'] = 'unrecognized';
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'bad_customize_changeset_status', $this->_last_response_parsed['data'] );
-
- // Disallowed publish posts if not allowed.
- $post_type_obj = get_post_type_object( 'customize_changeset' );
- $post_type_obj->cap->publish_posts = 'publish_customize_changesets';
- $_POST['customize_changeset_status'] = 'publish';
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'changeset_publish_unauthorized', $this->_last_response_parsed['data'] );
- $_POST['customize_changeset_status'] = 'future';
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'changeset_publish_unauthorized', $this->_last_response_parsed['data'] );
- $post_type_obj->cap->publish_posts = 'customize'; // Restore.
-
- // Validate date.
- $_POST['customize_changeset_status'] = 'draft';
- $_POST['customize_changeset_date'] = 'BAD DATE';
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'bad_customize_changeset_date', $this->_last_response_parsed['data'] );
- $_POST['customize_changeset_date'] = '2010-01-01 00:00:00';
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'not_future_date', $this->_last_response_parsed['data']['code'] );
- $_POST['customize_changeset_date'] = ( gmdate( 'Y' ) + 1 ) . '-01-01 00:00:00';
- $this->make_ajax_call( 'customize_save' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $_POST['customize_changeset_status'] = 'future';
- $_POST['customize_changeset_date'] = '+10 minutes';
- $this->make_ajax_call( 'customize_save' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertSame( 'future', get_post_status( $wp_customize->changeset_post_id() ) );
- wp_update_post(
- array(
- 'ID' => $wp_customize->changeset_post_id(),
- 'post_status' => 'auto-draft',
- )
- );
- }
-
- /**
- * Set up valid user state.
- *
- * @param string $uuid Changeset UUID.
- * @return WP_Customize_Manager
- */
- protected function set_up_valid_state( $uuid = null ) {
- global $wp_customize;
- wp_set_current_user( self::$admin_user_id );
- $wp_customize = new WP_Customize_Manager(
- array(
- 'changeset_uuid' => $uuid,
- )
- );
- $wp_customize->register_controls();
- $nonce = wp_create_nonce( 'save-customize_' . $wp_customize->get_stylesheet() );
- $_POST['nonce'] = $nonce;
- $_GET['nonce'] = $nonce;
- $_REQUEST['nonce'] = $nonce;
- $wp_customize->setup_theme();
- return $wp_customize;
- }
-
- /**
- * Test WP_Customize_Manager::save().
- *
- * @ticket 30937
- *
- * @covers WP_Customize_Manager::save
- */
- public function test_save_success_publish_create() {
- $wp_customize = $this->set_up_valid_state();
-
- $_POST['customize_changeset_status'] = 'publish';
- $_POST['customize_changeset_title'] = 'Success Changeset';
- $_POST['customize_changeset_data'] = wp_json_encode(
- array(
- 'blogname' => array(
- 'value' => 'Successful Site Title',
- ),
- )
- );
- $this->make_ajax_call( 'customize_save' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertIsArray( $this->_last_response_parsed['data'] );
-
- $this->assertSame( 'publish', $this->_last_response_parsed['data']['changeset_status'] );
- $this->assertArrayHasKey( 'next_changeset_uuid', $this->_last_response_parsed['data'] );
- $this->assertTrue( wp_is_uuid( $this->_last_response_parsed['data']['next_changeset_uuid'], 4 ) );
- $this->assertSame( 'Success Changeset', get_post( $wp_customize->changeset_post_id() )->post_title );
- $this->assertSame( 'Successful Site Title', get_option( 'blogname' ) );
- }
-
- /**
- * Test WP_Customize_Manager::save().
- *
- * @ticket 30937
- *
- * @covers WP_Customize_Manager::save
- */
- public function test_save_success_publish_edit() {
- $uuid = wp_generate_uuid4();
-
- $post_id = self::factory()->post->create(
- array(
- 'post_name' => $uuid,
- 'post_title' => 'Original',
- 'post_type' => 'customize_changeset',
- 'post_status' => 'auto-draft',
- 'post_content' => wp_json_encode(
- array(
- 'blogname' => array(
- 'value' => 'New Site Title',
- ),
- )
- ),
- )
- );
- $wp_customize = $this->set_up_valid_state( $uuid );
-
- $_POST['customize_changeset_status'] = 'publish';
- $_POST['customize_changeset_title'] = 'Published';
- $this->make_ajax_call( 'customize_save' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertIsArray( $this->_last_response_parsed['data'] );
-
- $this->assertSame( 'publish', $this->_last_response_parsed['data']['changeset_status'] );
- $this->assertArrayHasKey( 'next_changeset_uuid', $this->_last_response_parsed['data'] );
- $this->assertTrue( wp_is_uuid( $this->_last_response_parsed['data']['next_changeset_uuid'], 4 ) );
- $this->assertSame( 'New Site Title', get_option( 'blogname' ) );
- $this->assertSame( 'Published', get_post( $post_id )->post_title );
- }
-
- /**
- * Test WP_Customize_Manager::save().
- *
- * @ticket 38943
- *
- * @covers WP_Customize_Manager::save
- */
- public function test_success_save_post_date() {
- $uuid = wp_generate_uuid4();
- $post_id = self::factory()->post->create(
- array(
- 'post_name' => $uuid,
- 'post_title' => 'Original',
- 'post_type' => 'customize_changeset',
- 'post_status' => 'auto-draft',
- 'post_content' => wp_json_encode(
- array(
- 'blogname' => array(
- 'value' => 'New Site Title',
- ),
- )
- ),
- )
- );
- $wp_customize = $this->set_up_valid_state( $uuid );
-
- // Success future schedule date.
- $future_date = ( gmdate( 'Y' ) + 1 ) . '-01-01 00:00:00';
- $_POST['customize_changeset_status'] = 'future';
- $_POST['customize_changeset_title'] = 'Future date';
- $_POST['customize_changeset_date'] = $future_date;
- $this->make_ajax_call( 'customize_save' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertArrayHasKey( 'changeset_date', $this->_last_response_parsed['data'] );
- $changeset_post_schedule = get_post( $post_id );
- $this->assertSame( $future_date, $changeset_post_schedule->post_date );
-
- // Success future changeset change to draft keeping existing date.
- unset( $_POST['customize_changeset_date'] );
- $_POST['customize_changeset_status'] = 'draft';
- $this->make_ajax_call( 'customize_save' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertArrayNotHasKey( 'changeset_date', $this->_last_response_parsed['data'] );
- $changeset_post_draft = get_post( $post_id );
- $this->assertSame( $future_date, $changeset_post_draft->post_date );
-
- // Success if date is not passed with schedule changeset and stored changeset have future date.
- $_POST['customize_changeset_status'] = 'future';
- $this->make_ajax_call( 'customize_save' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertArrayHasKey( 'changeset_date', $this->_last_response_parsed['data'] );
- $changeset_post_schedule = get_post( $post_id );
- $this->assertSame( $future_date, $changeset_post_schedule->post_date );
- // Success if draft with past date.
- $now = current_time( 'mysql' );
- wp_update_post(
- array(
- 'ID' => $post_id,
- 'post_status' => 'draft',
- 'post_date' => $now,
- 'post_date_gmt' => get_gmt_from_date( $now ),
- )
- );
-
- // Fail if future request and existing date is past.
- $_POST['customize_changeset_status'] = 'future';
- unset( $_POST['customize_changeset_date'] );
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'not_future_date', $this->_last_response_parsed['data']['code'] );
-
- // Success publish changeset reset date to current.
- wp_update_post(
- array(
- 'ID' => $post_id,
- 'post_status' => 'future',
- 'post_date' => $future_date,
- 'post_date_gmt' => get_gmt_from_date( $future_date ),
- )
- );
- unset( $_POST['customize_changeset_date'] );
- $_POST['customize_changeset_status'] = 'publish';
- $this->make_ajax_call( 'customize_save' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertArrayHasKey( 'next_changeset_uuid', $this->_last_response_parsed['data'] );
- $this->assertTrue( wp_is_uuid( $this->_last_response_parsed['data']['next_changeset_uuid'], 4 ) );
- $changeset_post_publish = get_post( $post_id );
- $this->assertNotEquals( $future_date, $changeset_post_publish->post_date );
-
- // Check response when trying to update an already-published post.
- $this->assertSame( 'trash', get_post_status( $post_id ) );
- $_POST['customize_changeset_status'] = 'publish';
- $this->make_ajax_call( 'customize_save' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'changeset_already_published', $this->_last_response_parsed['data']['code'] );
- $this->assertArrayHasKey( 'next_changeset_uuid', $this->_last_response_parsed['data'] );
- $this->assertTrue( wp_is_uuid( $this->_last_response_parsed['data']['next_changeset_uuid'], 4 ) );
- }
-
- /**
- * Test WP_Customize_Manager::save().
- *
- * @ticket 39896
- *
- * @covers WP_Customize_Manager::save
- */
- public function test_save_autosave() {
- $uuid = wp_generate_uuid4();
-
- $post_id = self::factory()->post->create(
- array(
- 'post_name' => $uuid,
- 'post_type' => 'customize_changeset',
- 'post_status' => 'draft',
- 'post_content' => wp_json_encode(
- array(
- 'blogname' => array(
- 'value' => 'New Site Title',
- ),
- )
- ),
- )
- );
- $this->set_up_valid_state( $uuid );
-
- $this->assertFalse( wp_get_post_autosave( $post_id ) );
-
- $_POST['customize_changeset_data'] = wp_json_encode(
- array(
- 'blogname' => array(
- 'value' => 'Autosaved Site Title',
- ),
- )
- );
-
- $_POST['customize_changeset_autosave'] = 'on';
- $this->make_ajax_call( 'customize_save' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertSame( 'draft', $this->_last_response_parsed['data']['changeset_status'] );
- $autosave_revision = wp_get_post_autosave( $post_id );
- $this->assertInstanceOf( 'WP_Post', $autosave_revision );
-
- $this->assertStringContainsString( 'New Site Title', get_post( $post_id )->post_content );
- $this->assertStringContainsString( 'Autosaved Site Title', $autosave_revision->post_content );
- }
-
- /**
- * Test request for trashing a changeset.
- *
- * @ticket 39896
- *
- * @covers WP_Customize_Manager::handle_changeset_trash_request
- */
- public function test_handle_changeset_trash_request() {
- $uuid = wp_generate_uuid4();
- $wp_customize = $this->set_up_valid_state( $uuid );
-
- $this->make_ajax_call( 'customize_trash' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'invalid_nonce', $this->_last_response_parsed['data']['code'] );
-
- $nonce = wp_create_nonce( 'trash_customize_changeset' );
- $_POST['nonce'] = $nonce;
- $_GET['nonce'] = $nonce;
- $_REQUEST['nonce'] = $nonce;
- $this->make_ajax_call( 'customize_trash' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'non_existent_changeset', $this->_last_response_parsed['data']['code'] );
-
- $wp_customize->register_controls(); // And settings too.
- $wp_customize->set_post_value( 'blogname', 'HELLO' );
- $wp_customize->save_changeset_post(
- array(
- 'status' => 'save',
- )
- );
-
- add_filter( 'map_meta_cap', array( $this, 'return_do_not_allow' ) );
- $this->make_ajax_call( 'customize_trash' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'changeset_trash_unauthorized', $this->_last_response_parsed['data']['code'] );
- remove_filter( 'map_meta_cap', array( $this, 'return_do_not_allow' ) );
-
- $lock_user_id = static::factory()->user->create( array( 'role' => 'administrator' ) );
- $previous_user = get_current_user_id();
- wp_set_current_user( $lock_user_id );
- $wp_customize->set_changeset_lock( $wp_customize->changeset_post_id() );
- wp_set_current_user( $previous_user );
- $this->make_ajax_call( 'customize_trash' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'changeset_locked', $this->_last_response_parsed['data']['code'] );
- delete_post_meta( $wp_customize->changeset_post_id(), '_edit_lock' );
-
- wp_update_post(
- array(
- 'ID' => $wp_customize->changeset_post_id(),
- 'post_status' => 'trash',
- )
- );
- $this->make_ajax_call( 'customize_trash' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'changeset_already_trashed', $this->_last_response_parsed['data']['code'] );
-
- wp_update_post(
- array(
- 'ID' => $wp_customize->changeset_post_id(),
- 'post_status' => 'draft',
- )
- );
-
- $wp_trash_post_count = did_action( 'wp_trash_post' );
- add_filter( 'pre_trash_post', '__return_false' );
- $this->make_ajax_call( 'customize_trash' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'changeset_trash_failure', $this->_last_response_parsed['data']['code'] );
- remove_filter( 'pre_trash_post', '__return_false' );
- $this->assertSame( $wp_trash_post_count, did_action( 'wp_trash_post' ) );
-
- $wp_trash_post_count = did_action( 'wp_trash_post' );
- $this->assertSame( 'draft', get_post_status( $wp_customize->changeset_post_id() ) );
- $this->make_ajax_call( 'customize_trash' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertSame( 'trash', get_post_status( $wp_customize->changeset_post_id() ) );
- $this->assertSame( $wp_trash_post_count + 1, did_action( 'wp_trash_post' ) );
- }
-
- /**
- * Return caps array containing 'do_not_allow'.
- *
- * @return array Caps.
- */
- public function return_do_not_allow() {
- return array( 'do_not_allow' );
- }
-
- /**
- * Test request for dismissing autosave changesets.
- *
- * @ticket 39896
- * @covers WP_Customize_Manager::handle_dismiss_autosave_or_lock_request
- * @covers WP_Customize_Manager::dismiss_user_auto_draft_changesets
- */
- public function test_handle_dismiss_autosave_or_lock_request() {
- $uuid = wp_generate_uuid4();
- $wp_customize = $this->set_up_valid_state( $uuid );
- $valid_user_id = get_current_user_id();
-
- // Temporarily remove user to test requirement that user is logged in. See #42450.
- wp_set_current_user( 0 );
- $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'unauthenticated', $this->_last_response_parsed['data'] );
- wp_set_current_user( $valid_user_id );
-
- $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'invalid_nonce', $this->_last_response_parsed['data'] );
-
- $nonce = wp_create_nonce( 'customize_dismiss_autosave_or_lock' );
- $_POST['nonce'] = $nonce;
- $_GET['nonce'] = $nonce;
- $_REQUEST['nonce'] = $nonce;
-
- $_POST['dismiss_lock'] = true;
- $_GET['dismiss_lock'] = true;
- $_REQUEST['dismiss_lock'] = true;
- $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'no_changeset_to_dismiss_lock', $this->_last_response_parsed['data'] );
-
- $_POST['dismiss_autosave'] = true;
- $_GET['dismiss_autosave'] = true;
- $_REQUEST['dismiss_autosave'] = true;
- $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'no_auto_draft_to_delete', $this->_last_response_parsed['data'] );
-
- $other_user_id = self::factory()->user->create();
-
- // Create auto-drafts.
- $user_auto_draft_ids = array();
- for ( $i = 0; $i < 3; $i++ ) {
- $user_auto_draft_ids[] = self::factory()->post->create(
- array(
- 'post_name' => wp_generate_uuid4(),
- 'post_type' => 'customize_changeset',
- 'post_status' => 'auto-draft',
- 'post_author' => self::$admin_user_id,
- 'post_content' => wp_json_encode( array() ),
- )
- );
- }
- $other_user_auto_draft_ids = array();
- for ( $i = 0; $i < 3; $i++ ) {
- $other_user_auto_draft_ids[] = self::factory()->post->create(
- array(
- 'post_name' => wp_generate_uuid4(),
- 'post_type' => 'customize_changeset',
- 'post_status' => 'auto-draft',
- 'post_author' => $other_user_id,
- 'post_content' => wp_json_encode( array() ),
- )
- );
- }
- foreach ( array_merge( $user_auto_draft_ids, $other_user_auto_draft_ids ) as $post_id ) {
- $this->assertFalse( (bool) get_post_meta( $post_id, '_customize_restore_dismissed', true ) );
- }
- $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertSame( 'auto_draft_dismissed', $this->_last_response_parsed['data'] );
- foreach ( $user_auto_draft_ids as $post_id ) {
- $this->assertSame( 'auto-draft', get_post_status( $post_id ) );
- $this->assertTrue( (bool) get_post_meta( $post_id, '_customize_restore_dismissed', true ) );
- }
- foreach ( $other_user_auto_draft_ids as $post_id ) {
- $this->assertSame( 'auto-draft', get_post_status( $post_id ) );
- $this->assertFalse( (bool) get_post_meta( $post_id, '_customize_restore_dismissed', true ) );
- }
-
- // Subsequent test results in none dismissed.
- $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'no_auto_draft_to_delete', $this->_last_response_parsed['data'] );
-
- // Save a changeset as a draft.
- $r = $wp_customize->save_changeset_post(
- array(
- 'data' => array(
- 'blogname' => array(
- 'value' => 'Foo',
- ),
- ),
- 'status' => 'draft',
- )
- );
-
- $_POST['dismiss_autosave'] = false;
- $_GET['dismiss_autosave'] = false;
- $_REQUEST['dismiss_autosave'] = false;
- $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertSame( 'changeset_lock_dismissed', $this->_last_response_parsed['data'] );
-
- $_POST['dismiss_autosave'] = true;
- $_GET['dismiss_autosave'] = true;
- $_REQUEST['dismiss_autosave'] = true;
- $this->assertNotWPError( $r );
- $this->assertFalse( wp_get_post_autosave( $wp_customize->changeset_post_id() ) );
- $this->assertStringContainsString( 'Foo', get_post( $wp_customize->changeset_post_id() )->post_content );
-
- // Since no autosave yet, confirm no action.
- $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'no_autosave_revision_to_delete', $this->_last_response_parsed['data'] );
-
- // Add the autosave revision.
- $r = $wp_customize->save_changeset_post(
- array(
- 'data' => array(
- 'blogname' => array(
- 'value' => 'Bar',
- ),
- ),
- 'autosave' => true,
- )
- );
- $this->assertNotWPError( $r );
- $autosave_revision = wp_get_post_autosave( $wp_customize->changeset_post_id() );
- $this->assertInstanceOf( 'WP_Post', $autosave_revision );
- $this->assertStringContainsString( 'Foo', get_post( $wp_customize->changeset_post_id() )->post_content );
- $this->assertStringContainsString( 'Bar', $autosave_revision->post_content );
-
- // Confirm autosave gets deleted.
- $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertSame( 'autosave_revision_deleted', $this->_last_response_parsed['data'] );
- $this->assertFalse( wp_get_post_autosave( $wp_customize->changeset_post_id() ) );
-
- // Since no autosave yet, confirm no action.
- $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'no_autosave_revision_to_delete', $this->_last_response_parsed['data'] );
- }
-
- /**
- * Test request for retrieving installed themes.
- *
- * @ticket 54549
- * @covers WP_Customize_Manager::handle_load_themes_request
- */
- public function test_wp_ajax_customize_load_themes_action() {
- $arguments = array(
- 'changeset_uuid' => false,
- 'settings_previewed' => true,
- 'branching' => false,
- );
- new WP_Customize_Manager( $arguments );
- wp_set_current_user( self::$admin_user_id );
- $nonce = wp_create_nonce( 'switch_themes' );
- $_POST['nonce'] = $nonce;
- $_GET['nonce'] = $nonce;
- $_REQUEST['nonce'] = $nonce;
- $_POST['theme_action'] = 'installed';
- $this->make_ajax_call( 'customize_load_themes' );
- $response = $this->_last_response_parsed;
- $this->assertIsArray( $response, 'Response is not an array' );
-
- $this->assertArrayHasKey( 'success', $response, 'Response must have a "success" key' );
- $this->assertTrue( $response['success'], 'Response was not "success"' );
-
- $this->assertArrayHasKey( 'data', $response, 'Response must have a "data" key' );
- $this->assertIsArray( $response['data'], 'The response "data" is not an array' );
- $this->assertArrayHasKey( 'themes', $response['data'], 'The response data must have a "themes" key' );
- $this->assertIsArray( $response['data']['themes'], 'Themes data is not an array' );
- $this->assertNotEmpty( $response['data']['themes'], 'Themes data must not be empty' );
-
- foreach ( $response['data']['themes'] as $theme ) {
- $this->assertIsArray( $theme, 'Theme is not an array' );
- $this->assertNotEmpty( $theme, 'Theme data must not be empty' );
- $this->assertArrayHasKey( 'id', $theme, 'Theme data must have an "id" key' );
- $this->assertNotEmpty( $theme['id'], 'Theme id cannot be empty' );
-
- $this->assertArrayHasKey( 'name', $theme, 'Theme data must have a "name" key' );
- $this->assertNotEmpty( $theme['name'], 'Theme name cannot be empty' );
-
- $this->assertArrayHasKey( 'blockTheme', $theme, 'Themes data must include information about blocks support' );
- }
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxCustomizeMenusphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/CustomizeMenus.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/CustomizeMenus.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/CustomizeMenus.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,799 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Testing Ajax customize menus functionality.
- *
- * @package WordPress
- * @subpackage UnitTests
- * @since 4.3.0
- * @group ajax
- */
-class Tests_Ajax_CustomizeMenus extends WP_Ajax_UnitTestCase {
-
- /**
- * Instance of WP_Customize_Manager which is reset for each test.
- *
- * @var WP_Customize_Manager
- */
- public $wp_customize;
-
- /**
- * Page IDs.
- *
- * @var int[]
- */
- public static $pages;
-
- /**
- * Post IDs.
- *
- * @var int[]
- */
- public static $posts;
-
- /**
- * Term IDs.
- *
- * @var int[]
- */
- public static $terms;
-
- public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
- // Make some post objects.
- self::$posts = $factory->post->create_many( 5 );
- self::$pages = $factory->post->create_many( 5, array( 'post_type' => 'page' ) );
-
- // Some terms too.
- self::$terms = $factory->term->create_many( 5 );
- }
-
- /**
- * Set up the test fixture.
- */
- public function set_up() {
- parent::set_up();
- require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
- wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
- global $wp_customize;
- $this->wp_customize = new WP_Customize_Manager();
- $wp_customize = $this->wp_customize;
- }
-
- /**
- * Helper to keep it DRY
- *
- * @param string $action Action.
- */
- protected function make_ajax_call( $action ) {
- // Make the request.
- try {
- $this->_handleAjax( $action );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
- }
-
- /**
- * Testing capabilities check for ajax_load_available_items method
- *
- * @dataProvider data_ajax_load_available_items_cap_check
- *
- * @covers WP_Customize_Nav_Menus::ajax_load_available_items
- *
- * @param string $role The role we're checking caps against.
- * @param array $expected_results Expected results.
- */
- public function test_ajax_load_available_items_cap_check( $role, $expected_results ) {
-
- if ( 'administrator' !== $role ) {
- // If we're not an admin, we should get a wp_die( -1 ).
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- }
-
- wp_set_current_user( self::factory()->user->create( array( 'role' => $role ) ) );
-
- $_POST = array(
- 'action' => 'load-available-menu-items-customizer',
- 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
- );
-
- $this->make_ajax_call( 'load-available-menu-items-customizer' );
-
- // If we are an admin, we should get a proper response.
- if ( 'administrator' === $role ) {
- // Get the results.
- $response = json_decode( $this->_last_response, true );
-
- $this->assertSame( $expected_results, $response );
- }
-
- }
-
- /**
- * Data provider for test_ajax_load_available_items_cap_check().
- *
- * Provides various post_args to induce error messages in the that can be
- * compared to the expected_results.
- *
- * @since 4.3.0
- *
- * @return array {
- * @type array {
- * @string string $role The role that will test caps for.
- * @array array $expected_results The expected results from the Ajax call.
- * }
- * }
- */
- public function data_ajax_load_available_items_cap_check() {
- return array(
- array(
- 'subscriber',
- array(),
- ),
- array(
- 'contributor',
- array(),
- ),
- array(
- 'author',
- array(),
- ),
- array(
- 'editor',
- array(),
- ),
- array(
- 'administrator',
- array(
- 'success' => false,
- 'data' => 'nav_menus_missing_type_or_object_parameter',
- ),
- ),
- );
- }
-
- /**
- * Testing the error messaging for ajax_load_available_items
- *
- * @dataProvider data_ajax_load_available_items_error_messages
- *
- * @covers WP_Customize_Nav_Menus::ajax_load_available_items
- *
- * @param array $post_args POST args.
- * @param mixed $expected_results Expected results.
- */
- public function test_ajax_load_available_items_error_messages( $post_args, $expected_results ) {
-
- $_POST = array_merge(
- array(
- 'action' => 'load-available-menu-items-customizer',
- 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
- ),
- $post_args
- );
-
- // Make the request.
- $this->make_ajax_call( 'load-available-menu-items-customizer' );
-
- // Get the results.
- $response = json_decode( $this->_last_response, true );
-
- $this->assertSame( $expected_results, $response );
- }
-
- /**
- * Data provider for test_ajax_load_available_items_error_message().
- *
- * Provides various post_args to induce error messages in the that can be
- * compared to the expected_results.
- *
- * @since 4.3.0
- *
- * @return array {
- * @type array {
- * @array array $post_args The arguments that will merged with the $_POST array.
- * @array array $expected_results The expected results from the Ajax call.
- * }
- * }
- */
- public function data_ajax_load_available_items_error_messages() {
- return array(
- // Testing empty obj_type and type.
- array(
- array(
- 'type' => '',
- 'object' => '',
- ),
- array(
- 'success' => false,
- 'data' => 'nav_menus_missing_type_or_object_parameter',
- ),
- ),
- // Testing empty obj_type.
- array(
- array(
- 'type' => 'post_type',
- 'object' => '',
- ),
- array(
- 'success' => false,
- 'data' => 'nav_menus_missing_type_or_object_parameter',
- ),
- ),
- // Testing empty type.
- array(
- array(
- 'type' => '',
- 'object' => 'post',
- ),
- array(
- 'success' => false,
- 'data' => 'nav_menus_missing_type_or_object_parameter',
- ),
- ),
- // Testing empty type of a bulk request.
- array(
- array(
- 'item_types' => array(
- array(
- 'type' => 'post_type',
- 'object' => 'post',
- ),
- array(
- 'type' => 'post_type',
- 'object' => '',
- ),
- ),
- ),
- array(
- 'success' => false,
- 'data' => 'nav_menus_missing_type_or_object_parameter',
- ),
- ),
- // Testing incorrect type option.
- array(
- array(
- 'type' => 'post_type',
- 'object' => 'invalid',
- ),
- array(
- 'success' => false,
- 'data' => 'nav_menus_invalid_post_type',
- ),
- ),
- );
- }
-
- /**
- * Testing the success status.
- *
- * @dataProvider data_ajax_load_available_items_success_status
- *
- * @covers WP_Customize_Nav_Menus::ajax_load_available_items
- *
- * @param array $post_args POST args.
- * @param array $success_status Success status.
- */
- public function test_ajax_load_available_items_success_status( $post_args, $success_status ) {
-
- $_POST = array_merge(
- array(
- 'action' => 'load-available-menu-items-customizer',
- 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
- ),
- $post_args
- );
-
- // Make the request.
- $this->make_ajax_call( 'load-available-menu-items-customizer' );
-
- // Get the results.
- $response = json_decode( $this->_last_response, true );
- $this->assertSame( $success_status, $response['success'] );
-
- }
-
- /**
- * Data provider for test_ajax_load_available_items_success_status().
- *
- * Provides various post_args to retrieve results and compare against
- * the success status.
- *
- * @since 4.3.0
- *
- * @return array {
- * @type array {
- * @type array $post_args The arguments that will merged with the $_POST array.
- * @type bool $success_status The expected success status.
- * }
- * }
- */
- public function data_ajax_load_available_items_success_status() {
- return array(
- array(
- array(
- 'type' => 'post_type',
- 'object' => 'post',
- ),
- true,
- ),
- array(
- array(
- 'type' => 'post_type',
- 'object' => 'page',
- ),
- true,
- ),
- array(
- array(
- 'type' => 'post_type',
- 'object' => 'custom',
- ),
- false,
- ),
- array(
- array(
- 'type' => 'taxonomy',
- 'object' => 'post_tag',
- ),
- true,
- ),
- // Testing a bulk request.
- array(
- array(
- 'item_types' => array(
- array(
- 'type' => 'post_type',
- 'object' => 'post',
- ),
- array(
- 'type' => 'post_type',
- 'object' => 'page',
- ),
- ),
- ),
- true,
- ),
- );
- }
-
- /**
- * Testing the array structure for a single item
- *
- * @dataProvider data_ajax_load_available_items_structure
- *
- * @covers WP_Customize_Nav_Menus::ajax_load_available_items
- *
- * @param array $post_args POST args.
- */
- public function test2_ajax_load_available_items_structure( $post_args ) {
- do_action( 'customize_register', $this->wp_customize );
-
- $expected_keys = array(
- 'id',
- 'title',
- 'type',
- 'type_label',
- 'object',
- 'object_id',
- 'url',
- );
-
- $auto_draft_post = $this->wp_customize->nav_menus->insert_auto_draft_post(
- array(
- 'post_title' => 'Test Auto Draft',
- 'post_type' => 'post',
- )
- );
- $this->wp_customize->set_post_value( 'nav_menus_created_posts', array( $auto_draft_post->ID ) );
- $this->wp_customize->get_setting( 'nav_menus_created_posts' )->preview();
-
- $_POST = array_merge(
- array(
- 'action' => 'load-available-menu-items-customizer',
- 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
- ),
- $post_args
- );
-
- // Make the request.
- $this->make_ajax_call( 'load-available-menu-items-customizer' );
-
- // Get the results.
- $response = json_decode( $this->_last_response, true );
-
- $this->assertNotEmpty( current( $response['data']['items'] ) );
-
- // Get the second index to avoid the home page edge case.
- $first_prop = current( $response['data']['items'] );
- $test_item = $first_prop[1];
-
- foreach ( $expected_keys as $key ) {
- $this->assertArrayHasKey( $key, $test_item );
- $this->assertNotEmpty( $test_item[ $key ] );
- }
-
- // Special test for the home page.
- if ( 'page' === $test_item['object'] ) {
- $first_prop = current( $response['data']['items'] );
- $home = $first_prop[0];
- foreach ( $expected_keys as $key ) {
- if ( 'object_id' !== $key ) {
- $this->assertArrayHasKey( $key, $home );
- if ( 'object' !== $key ) {
- $this->assertNotEmpty( $home[ $key ] );
- }
- }
- }
- } elseif ( 'post' === $test_item['object'] ) {
- $item_ids = wp_list_pluck( $response['data']['items']['post_type:post'], 'id' );
- $this->assertContains( 'post-' . $auto_draft_post->ID, $item_ids );
- }
- }
-
- /**
- * Data provider for test_ajax_load_available_items_structure().
- *
- * Provides various post_args to return a list of items to test the array structure of.
- *
- * @since 4.3.0
- *
- * @return array {
- * @type array {
- * @type array $post_args The arguments that will merged with the $_POST array.
- * }
- * }
- */
- public function data_ajax_load_available_items_structure() {
- return array(
- array(
- array(
- 'type' => 'post_type',
- 'object' => 'post',
- ),
- ),
- array(
- array(
- 'type' => 'post_type',
- 'object' => 'page',
- ),
- ),
- array(
- array(
- 'type' => 'taxonomy',
- 'object' => 'post_tag',
- ),
- ),
- );
- }
-
- /**
- * Testing the error messages for ajax_search_available_items
- *
- * @dataProvider data_ajax_search_available_items_caps_check
- *
- * @covers WP_Customize_Nav_Menus::ajax_search_available_items
- * @covers WP_Customize_Nav_Menus::search_available_items_query
- *
- * @param string $role Role.
- * @param array $expected_results Expected results.
- */
- public function test_ajax_search_available_items_caps_check( $role, $expected_results ) {
-
- if ( 'administrator' !== $role ) {
- // If we're not an admin, we should get a wp_die( -1 ).
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- }
-
- wp_set_current_user( self::factory()->user->create( array( 'role' => $role ) ) );
-
- $_POST = array(
- 'action' => 'search-available-menu-items-customizer',
- 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
- );
-
- $this->make_ajax_call( 'search-available-menu-items-customizer' );
-
- // If we are an admin, we should get a proper response.
- if ( 'administrator' === $role ) {
- // Get the results.
- $response = json_decode( $this->_last_response, true );
-
- $this->assertSame( $expected_results, $response );
- }
- }
-
- /**
- * Data provider for test_ajax_search_available_items_caps_check().
- *
- * Provides various post_args to induce error messages in the that can be
- * compared to the expected_results.
- *
- * @since 4.3.0
- *
- * @todo Make this more DRY
- *
- * @return array {
- * @type array {
- * @string string $role The role that will test caps for.
- * @array array $expected_results The expected results from the Ajax call.
- * }
- * }
- */
- public function data_ajax_search_available_items_caps_check() {
- return array(
- array(
- 'subscriber',
- array(),
- ),
- array(
- 'contributor',
- array(),
- ),
- array(
- 'author',
- array(),
- ),
- array(
- 'editor',
- array(),
- ),
- array(
- 'administrator',
- array(
- 'success' => false,
- 'data' => 'nav_menus_missing_search_parameter',
- ),
- ),
- );
- }
-
- /**
- * Testing the results of various searches
- *
- * @dataProvider data_ajax_search_available_items_results
- *
- * @covers WP_Customize_Nav_Menus::ajax_search_available_items
- * @covers WP_Customize_Nav_Menus::search_available_items_query
- *
- * @param array $post_args POST args.
- * @param array $expected_results Expected results.
- */
- public function test_ajax_search_available_items_results( $post_args, $expected_results ) {
- do_action( 'customize_register', $this->wp_customize );
-
- self::factory()->post->create_many( 5, array( 'post_title' => 'Test Post' ) );
- $included_auto_draft_post = $this->wp_customize->nav_menus->insert_auto_draft_post(
- array(
- 'post_title' => 'Test Included Auto Draft',
- 'post_type' => 'post',
- )
- );
- $excluded_auto_draft_post = $this->wp_customize->nav_menus->insert_auto_draft_post(
- array(
- 'post_title' => 'Excluded Auto Draft',
- 'post_type' => 'post',
- )
- );
- $this->wp_customize->set_post_value( 'nav_menus_created_posts', array( $included_auto_draft_post->ID, $excluded_auto_draft_post->ID ) );
- $this->wp_customize->get_setting( 'nav_menus_created_posts' )->preview();
-
- $_POST = array_merge(
- array(
- 'action' => 'search-available-menu-items-customizer',
- 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
- ),
- $post_args
- );
-
- $this->make_ajax_call( 'search-available-menu-items-customizer' );
-
- $response = json_decode( $this->_last_response, true );
-
- if ( isset( $post_args['search'] ) && 'test' === $post_args['search'] ) {
- $this->assertTrue( $response['success'] );
- $this->assertCount( 6, $response['data']['items'] );
- $item_ids = wp_list_pluck( $response['data']['items'], 'id' );
- $this->assertContains( 'post-' . $included_auto_draft_post->ID, $item_ids );
- $this->assertNotContains( 'post-' . $excluded_auto_draft_post->ID, $item_ids );
- } else {
- $this->assertSame( $expected_results, $response );
- }
- }
-
- /**
- * Data provider for test_ajax_search_available_items_results().
- *
- * Provides various post_args to test the results.
- *
- * @since 4.3.0
- *
- * @return array {
- * @type array {
- * @string string $post_args The args that will be passed to Ajax.
- * @array array $expected_results The expected results from the Ajax call.
- * }
- * }
- */
- public function data_ajax_search_available_items_results() {
- return array(
- array(
- array(),
- array(
- 'success' => false,
- 'data' => 'nav_menus_missing_search_parameter',
- ),
- ),
- array(
- array(
- 'search' => 'all_the_things',
- ),
- array(
- 'success' => false,
- 'data' => array(
- 'message' => 'No results found.',
- ),
- ),
- ),
- array(
- array(
- 'search' => 'test',
- ),
- array(
- 'success' => true,
- array(),
- ),
- ),
- );
- }
-
- /**
- * Testing successful ajax_insert_auto_draft_post() call.
- *
- * @covers WP_Customize_Nav_Menus::ajax_insert_auto_draft_post
- * @covers WP_Customize_Nav_Menus::insert_auto_draft_post
- */
- public function test_ajax_insert_auto_draft_post_success() {
- $_POST = wp_slash(
- array(
- 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
- 'params' => array(
- 'post_type' => 'post',
- 'post_title' => 'Hello World',
- ),
- )
- );
- $this->_last_response = '';
- $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
- $response = json_decode( $this->_last_response, true );
-
- $this->assertTrue( $response['success'] );
- $this->assertArrayHasKey( 'post_id', $response['data'] );
- $this->assertArrayHasKey( 'url', $response['data'] );
- $post = get_post( $response['data']['post_id'] );
- $this->assertSame( 'Hello World', $post->post_title );
- $this->assertSame( 'post', $post->post_type );
- $this->assertSame( '', $post->post_name );
- $this->assertSame( 'hello-world', get_post_meta( $post->ID, '_customize_draft_post_name', true ) );
- $this->assertSame( $this->wp_customize->changeset_uuid(), get_post_meta( $post->ID, '_customize_changeset_uuid', true ) );
- }
-
- /**
- * Testing unsuccessful ajax_insert_auto_draft_post() call.
- *
- * @covers WP_Customize_Nav_Menus::ajax_insert_auto_draft_post
- */
- public function test_ajax_insert_auto_draft_failures() {
- // No nonce.
- $_POST = array();
- $this->_last_response = '';
- $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
- $response = json_decode( $this->_last_response, true );
- $this->assertFalse( $response['success'] );
- $this->assertSame( 'bad_nonce', $response['data'] );
-
- // Bad nonce.
- $_POST = wp_slash(
- array(
- 'customize-menus-nonce' => 'bad',
- )
- );
- $this->_last_response = '';
- $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
- $response = json_decode( $this->_last_response, true );
- $this->assertFalse( $response['success'] );
- $this->assertSame( 'bad_nonce', $response['data'] );
-
- // Bad nonce.
- wp_set_current_user( self::factory()->user->create( array( 'role' => 'subscriber' ) ) );
- $_POST = wp_slash(
- array(
- 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
- )
- );
- $this->_last_response = '';
- $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
- $response = json_decode( $this->_last_response, true );
- $this->assertFalse( $response['success'] );
- $this->assertSame( 'customize_not_allowed', $response['data'] );
-
- // Missing params.
- wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
- $_POST = wp_slash(
- array(
- 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
- )
- );
- $this->_last_response = '';
- $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
- $response = json_decode( $this->_last_response, true );
- $this->assertFalse( $response['success'] );
- $this->assertSame( 'missing_params', $response['data'] );
-
- // insufficient_post_permissions.
- register_post_type( 'privilege', array( 'capability_type' => 'privilege' ) );
- $_POST = wp_slash(
- array(
- 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
- 'params' => array(
- 'post_type' => 'privilege',
- ),
- )
- );
- $this->_last_response = '';
- $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
- $response = json_decode( $this->_last_response, true );
- $this->assertFalse( $response['success'] );
- $this->assertSame( 'insufficient_post_permissions', $response['data'] );
-
- // insufficient_post_permissions.
- $_POST = wp_slash(
- array(
- 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
- 'params' => array(
- 'post_type' => 'non-existent',
- ),
- )
- );
- $this->_last_response = '';
- $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
- $response = json_decode( $this->_last_response, true );
- $this->assertFalse( $response['success'] );
- $this->assertSame( 'missing_post_type_param', $response['data'] );
-
- // missing_post_title.
- $_POST = wp_slash(
- array(
- 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
- 'params' => array(
- 'post_type' => 'post',
- 'post_title' => ' ',
- ),
- )
- );
- $this->_last_response = '';
- $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
- $response = json_decode( $this->_last_response, true );
- $this->assertFalse( $response['success'] );
- $this->assertSame( 'missing_post_title', $response['data'] );
-
- // illegal_params.
- $_POST = wp_slash(
- array(
- 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
- 'params' => array(
- 'post_type' => 'post',
- 'post_title' => 'OK',
- 'post_name' => 'bad',
- 'post_content' => 'bad',
- ),
- )
- );
- $this->_last_response = '';
- $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
- $response = json_decode( $this->_last_response, true );
- $this->assertFalse( $response['success'] );
- $this->assertSame( 'illegal_params', $response['data'] );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxDeleteCommentphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/DeleteComment.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/DeleteComment.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/DeleteComment.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,366 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Ajax comment functionality.
- *
- * @package WordPress
- * @subpackage UnitTests
- * @since 3.4.0
- * @group ajax
- */
-class Tests_Ajax_DeleteComment extends WP_Ajax_UnitTestCase {
-
- /**
- * List of comments.
- *
- * @var array
- */
- protected static $comments = array();
-
- /**
- * ID of a post.
- *
- * @var int
- */
- protected static $post_id;
-
- public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
- self::$post_id = $factory->post->create();
-
- $comment_ids = $factory->comment->create_post_comments( self::$post_id, 8 );
- self::$comments = array_map( 'get_comment', $comment_ids );
- }
-
- /**
- * Clears the POST actions in between requests.
- */
- protected function _clear_post_action() {
- unset( $_POST['trash'] );
- unset( $_POST['untrash'] );
- unset( $_POST['spam'] );
- unset( $_POST['unspam'] );
- unset( $_POST['delete'] );
- $this->_last_response = '';
- }
-
- /*
- * Test prototype
- */
-
- /**
- * Tests as a privileged user (administrator).
- *
- * Expects test to pass.
- *
- * @covers ::wp_ajax_delete_comment
- * @covers ::_wp_ajax_delete_comment_response
- *
- * @param WP_Comment $comment Comment object.
- * @param string $action Action: 'trash', 'untrash', etc.
- */
- public function _test_as_admin( $comment, $action ) {
-
- // Reset request.
- $this->_clear_post_action();
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_POST['id'] = $comment->comment_ID;
- $_POST['_ajax_nonce'] = wp_create_nonce( 'delete-comment_' . $comment->comment_ID );
- $_POST[ $action ] = 1;
- $_POST['_total'] = count( self::$comments );
- $_POST['_per_page'] = 100;
- $_POST['_page'] = 1;
- $_POST['_url'] = admin_url( 'edit-comments.php' );
-
- // Make the request.
- try {
- $this->_handleAjax( 'delete-comment' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
-
- // Ensure everything is correct.
- $this->assertSame( $comment->comment_ID, (string) $xml->response[0]->comment['id'] );
- $this->assertSame( 'delete-comment_' . $comment->comment_ID, (string) $xml->response['action'] );
- $this->assertGreaterThanOrEqual( time() - 10, (int) $xml->response[0]->comment[0]->supplemental[0]->time[0] );
- $this->assertLessThanOrEqual( time(), (int) $xml->response[0]->comment[0]->supplemental[0]->time[0] );
-
- // 'trash', 'spam', 'delete' should make the total go down.
- if ( in_array( $action, array( 'trash', 'spam', 'delete' ), true ) ) {
- $total = $_POST['_total'] - 1;
-
- // 'unspam', 'untrash' should make the total go up.
- } elseif ( in_array( $action, array( 'untrash', 'unspam' ), true ) ) {
- $total = $_POST['_total'] + 1;
- }
-
- // The total is calculated based on a page break -OR- a random number. Let's look for both possible outcomes.
- $comment_count = wp_count_comments( 0 );
- $recalc_total = $comment_count->total_comments;
-
- // Check for either possible total.
- $message = sprintf( 'returned value: %1$d $total: %2$d $recalc_total: %3$d', (int) $xml->response[0]->comment[0]->supplemental[0]->total[0], $total, $recalc_total );
- $this->assertContains( (int) $xml->response[0]->comment[0]->supplemental[0]->total[0], array( $total, $recalc_total ), $message );
- }
-
- /**
- * Tests as a non-privileged user (subscriber).
- *
- * Expects test to fail.
- *
- * @covers ::wp_ajax_delete_comment
- *
- * @param WP_Comment $comment Comment object.
- * @param string $action Action: 'trash', 'untrash', etc.
- */
- public function _test_as_subscriber( $comment, $action ) {
-
- // Reset request.
- $this->_clear_post_action();
-
- // Become a subscriber.
- $this->_setRole( 'subscriber' );
-
- // Set up the $_POST request.
- $_POST['id'] = $comment->comment_ID;
- $_POST['_ajax_nonce'] = wp_create_nonce( 'delete-comment_' . $comment->comment_ID );
- $_POST[ $action ] = 1;
- $_POST['_total'] = count( self::$comments );
- $_POST['_per_page'] = 100;
- $_POST['_page'] = 1;
- $_POST['_url'] = admin_url( 'edit-comments.php' );
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'delete-comment' );
- }
-
-
- /**
- * Tests with a bad nonce.
- *
- * Expects test to fail.
- *
- * @covers ::wp_ajax_delete_comment
- *
- * @param WP_Comment $comment Comment object.
- * @param string $action Action: 'trash', 'untrash', etc.
- */
- public function _test_with_bad_nonce( $comment, $action ) {
-
- // Reset request.
- $this->_clear_post_action();
-
- // Become a subscriber.
- $this->_setRole( 'administrator' );
-
- // Set up the $_POST request.
- $_POST['id'] = $comment->comment_ID;
- $_POST['_ajax_nonce'] = wp_create_nonce( uniqid() );
- $_POST[ $action ] = 1;
- $_POST['_total'] = count( self::$comments );
- $_POST['_per_page'] = 100;
- $_POST['_page'] = 1;
- $_POST['_url'] = admin_url( 'edit-comments.php' );
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'delete-comment' );
- }
-
- /**
- * Tests with a bad ID.
- *
- * Expects test to fail.
- *
- * @covers ::wp_ajax_delete_comment
- *
- * @param WP_Comment $comment Comment object.
- * @param string $action Action: 'trash', 'untrash', etc.
- */
- public function _test_with_bad_id( $comment, $action ) {
-
- // Reset request.
- $this->_clear_post_action();
-
- // Become a subscriber.
- $this->_setRole( 'administrator' );
-
- // Set up the $_POST request.
- $_POST['id'] = 12346789;
- $_POST['_ajax_nonce'] = wp_create_nonce( 'delete-comment_12346789' );
- $_POST[ $action ] = 1;
- $_POST['_total'] = count( self::$comments );
- $_POST['_per_page'] = 100;
- $_POST['_page'] = 1;
- $_POST['_url'] = admin_url( 'edit-comments.php' );
-
- // Make the request, look for a timestamp in the exception.
- try {
- $this->_handleAjax( 'delete-comment' );
- $this->fail( 'Expected exception: WPAjaxDieStopException' );
- } catch ( WPAjaxDieStopException $e ) {
- $this->assertSame( 10, strlen( $e->getMessage() ) );
- $this->assertIsNumeric( $e->getMessage() );
- } catch ( Exception $e ) {
- $this->fail( 'Unexpected exception type: ' . get_class( $e ) );
- }
- }
-
- /**
- * Tests doubling the action (e.g. trash a trashed comment).
- *
- * Expects test to fail.
- *
- * @covers ::wp_ajax_delete_comment
- *
- * @param WP_Comment $comment Comment object.
- * @param string $action Action: 'trash', 'untrash', etc.
- */
- public function _test_double_action( $comment, $action ) {
-
- // Reset request.
- $this->_clear_post_action();
-
- // Become a subscriber.
- $this->_setRole( 'administrator' );
-
- // Set up the $_POST request.
- $_POST['id'] = $comment->comment_ID;
- $_POST['_ajax_nonce'] = wp_create_nonce( 'delete-comment_' . $comment->comment_ID );
- $_POST[ $action ] = 1;
- $_POST['_total'] = count( self::$comments );
- $_POST['_per_page'] = 100;
- $_POST['_page'] = 1;
- $_POST['_url'] = admin_url( 'edit-comments.php' );
-
- // Make the request.
- try {
- $this->_handleAjax( 'delete-comment' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
- $this->_last_response = '';
-
- // Force delete the comment.
- if ( 'delete' === $action ) {
- wp_delete_comment( $comment->comment_ID, true );
- }
-
- // Make the request again, look for a timestamp in the exception.
- try {
- $this->_handleAjax( 'delete-comment' );
- $this->fail( 'Expected exception: WPAjaxDieStopException' );
- } catch ( WPAjaxDieStopException $e ) {
- $this->assertSame( 10, strlen( $e->getMessage() ) );
- $this->assertIsNumeric( $e->getMessage() );
- } catch ( Exception $e ) {
- $this->fail( 'Unexpected exception type: ' . get_class( $e ) );
- }
- }
-
- /**
- * Deletes a comment as an administrator (expects success).
- *
- * @covers ::wp_ajax_delete_comment
- * @covers ::_wp_ajax_delete_comment_response
- */
- public function test_ajax_comment_trash_actions_as_administrator() {
- // Test trash/untrash.
- $this->_test_as_admin( self::$comments[0], 'trash' );
- $this->_test_as_admin( self::$comments[0], 'untrash' );
-
- // Test spam/unspam.
- $this->_test_as_admin( self::$comments[1], 'spam' );
- $this->_test_as_admin( self::$comments[1], 'unspam' );
-
- // Test delete.
- $this->_test_as_admin( self::$comments[2], 'delete' );
- }
-
- /**
- * Deletes a comment as a subscriber (expects permission denied).
- *
- * @covers ::wp_ajax_delete_comment
- */
- public function test_ajax_comment_trash_actions_as_subscriber() {
- // Test trash/untrash.
- $this->_test_as_subscriber( self::$comments[0], 'trash' );
- $this->_test_as_subscriber( self::$comments[0], 'untrash' );
-
- // Test spam/unspam.
- $this->_test_as_subscriber( self::$comments[1], 'spam' );
- $this->_test_as_subscriber( self::$comments[1], 'unspam' );
-
- // Test delete.
- $this->_test_as_subscriber( self::$comments[2], 'delete' );
- }
-
- /**
- * Deletes a comment with no ID.
- *
- * @covers ::wp_ajax_delete_comment
- * @covers ::_wp_ajax_delete_comment_response
- */
- public function test_ajax_trash_comment_no_id() {
- // Test trash/untrash.
- $this->_test_as_admin( self::$comments[0], 'trash' );
- $this->_test_as_admin( self::$comments[0], 'untrash' );
-
- // Test spam/unspam.
- $this->_test_as_admin( self::$comments[1], 'spam' );
- $this->_test_as_admin( self::$comments[1], 'unspam' );
-
- // Test delete.
- $this->_test_as_admin( self::$comments[2], 'delete' );
- }
-
- /**
- * Deletes a comment with a bad nonce.
- *
- * @covers ::wp_ajax_delete_comment
- */
- public function test_ajax_trash_comment_bad_nonce() {
- // Test trash/untrash.
- $this->_test_with_bad_nonce( self::$comments[0], 'trash' );
- $this->_test_with_bad_nonce( self::$comments[0], 'untrash' );
-
- // Test spam/unspam.
- $this->_test_with_bad_nonce( self::$comments[1], 'spam' );
- $this->_test_with_bad_nonce( self::$comments[1], 'unspam' );
-
- // Test delete.
- $this->_test_with_bad_nonce( self::$comments[2], 'delete' );
- }
-
- /**
- * Tests trashing an already trashed comment, etc.
- *
- * @covers ::wp_ajax_delete_comment
- */
- public function test_ajax_trash_double_action() {
- // Test trash/untrash.
- $this->_test_double_action( self::$comments[0], 'trash' );
- $this->_test_double_action( self::$comments[0], 'untrash' );
-
- // Test spam/unspam.
- $this->_test_double_action( self::$comments[1], 'spam' );
- $this->_test_double_action( self::$comments[1], 'unspam' );
-
- // Test delete.
- $this->_test_double_action( self::$comments[2], 'delete' );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxDeletePluginphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/DeletePlugin.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/DeletePlugin.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/DeletePlugin.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,165 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Ajax handler for deleting a plugin.
- *
- * @group ajax
- *
- * @covers ::wp_ajax_delete_plugin
- */
-class Tests_Ajax_Delete_Plugin extends WP_Ajax_UnitTestCase {
-
- public function test_missing_nonce() {
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'delete-plugin' );
- }
-
- public function test_missing_plugin() {
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
- $_POST['slug'] = 'foo';
-
- // Make the request.
- try {
- $this->_handleAjax( 'delete-plugin' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = array(
- 'success' => false,
- 'data' => array(
- 'slug' => '',
- 'errorCode' => 'no_plugin_specified',
- 'errorMessage' => 'No plugin specified.',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-
- public function test_missing_slug() {
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
- $_POST['plugin'] = 'foo/bar.php';
-
- // Make the request.
- try {
- $this->_handleAjax( 'delete-plugin' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = array(
- 'success' => false,
- 'data' => array(
- 'slug' => '',
- 'errorCode' => 'no_plugin_specified',
- 'errorMessage' => 'No plugin specified.',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-
- public function test_missing_capability() {
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
- $_POST['plugin'] = 'foo/bar.php';
- $_POST['slug'] = 'foo';
-
- // Make the request.
- try {
- $this->_handleAjax( 'delete-plugin' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = array(
- 'success' => false,
- 'data' => array(
- 'delete' => 'plugin',
- 'slug' => 'foo',
- 'errorMessage' => 'Sorry, you are not allowed to delete plugins for this site.',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-
- public function test_invalid_file() {
- $this->_setRole( 'administrator' );
-
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
- $_POST['plugin'] = '../foo/bar.php';
- $_POST['slug'] = 'foo';
-
- // Make the request.
- try {
- $this->_handleAjax( 'delete-plugin' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = array(
- 'success' => false,
- 'data' => array(
- 'delete' => 'plugin',
- 'slug' => 'foo',
- 'errorMessage' => 'Sorry, you are not allowed to delete plugins for this site.',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-
- /**
- * @group ms-excluded
- *
- * @covers ::wp_ajax_delete_plugin
- * @covers ::delete_plugins
- */
- public function test_delete_plugin() {
- $this->_setRole( 'administrator' );
-
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
- $_POST['plugin'] = 'foo.php';
- $_POST['slug'] = 'foo';
-
- // Make the request.
- try {
- $this->_handleAjax( 'delete-plugin' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = array(
- 'success' => true,
- 'data' => array(
- 'delete' => 'plugin',
- 'slug' => 'foo',
- 'plugin' => 'foo.php',
- 'pluginName' => '',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxDimCommentphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/DimComment.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/DimComment.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/DimComment.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,241 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Ajax comment functionality
- *
- * @package WordPress
- * @subpackage UnitTests
- * @since 3.4.0
- * @group ajax
- *
- * @covers ::wp_ajax_dim_comment
- */
-class Tests_Ajax_DimComment extends WP_Ajax_UnitTestCase {
-
- /**
- * List of comments.
- *
- * @var array
- */
- protected $_comments = array();
-
- /**
- * Sets up the test fixture.
- */
- public function set_up() {
- parent::set_up();
- $post_id = self::factory()->post->create();
- $this->_comments = self::factory()->comment->create_post_comments( $post_id, 15 );
- $this->_comments = array_map( 'get_comment', $this->_comments );
- }
-
- /**
- * Clears the POST actions in between requests.
- */
- protected function _clear_post_action() {
- unset( $_POST['id'] );
- unset( $_POST['new'] );
- $this->_last_response = '';
- }
-
- /*
- * Test prototype
- */
-
- /**
- * Tests as a privileged user (administrator).
- *
- * Expects test to pass.
- *
- * @param WP_Comment $comment Comment object.
- */
- public function _test_as_admin( $comment ) {
-
- // Reset request.
- $this->_clear_post_action();
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_POST['id'] = $comment->comment_ID;
- $_POST['_ajax_nonce'] = wp_create_nonce( 'approve-comment_' . $comment->comment_ID );
- $_POST['_total'] = count( $this->_comments );
- $_POST['_per_page'] = 100;
- $_POST['_page'] = 1;
- $_POST['_url'] = admin_url( 'edit-comments.php' );
-
- // Save the comment status.
- $prev_status = wp_get_comment_status( $comment->comment_ID );
-
- // Make the request.
- try {
- $this->_handleAjax( 'dim-comment' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
-
- // Ensure everything is correct.
- $this->assertSame( $comment->comment_ID, (string) $xml->response[0]->comment['id'] );
- $this->assertSame( 'dim-comment_' . $comment->comment_ID, (string) $xml->response['action'] );
- $this->assertGreaterThanOrEqual( time() - 10, (int) $xml->response[0]->comment[0]->supplemental[0]->time[0] );
- $this->assertLessThanOrEqual( time(), (int) $xml->response[0]->comment[0]->supplemental[0]->time[0] );
-
- // Check the status.
- $current = wp_get_comment_status( $comment->comment_ID );
- if ( in_array( $prev_status, array( 'unapproved', 'spam' ), true ) ) {
- $this->assertSame( 'approved', $current );
- } else {
- $this->assertSame( 'unapproved', $current );
- }
-
- // The total is calculated based on a page break -OR- a random number. Let's look for both possible outcomes.
- $comment_count = wp_count_comments( 0 );
- $recalc_total = $comment_count->total_comments;
-
- // Delta is not specified, it will always be 1 lower than the request.
- $total = $_POST['_total'] - 1;
-
- // Check for either possible total.
- $this->assertContains( (int) $xml->response[0]->comment[0]->supplemental[0]->total[0], array( $total, $recalc_total ) );
- }
-
- /**
- * Tests as a non-privileged user (subscriber).
- *
- * Expects test to fail.
- *
- * @param WP_Comment $comment Comment object.
- */
- public function _test_as_subscriber( $comment ) {
-
- // Reset request.
- $this->_clear_post_action();
-
- // Become a subscriber.
- $this->_setRole( 'subscriber' );
-
- // Set up the $_POST request.
- $_POST['id'] = $comment->comment_ID;
- $_POST['_ajax_nonce'] = wp_create_nonce( 'approve-comment_' . $comment->comment_ID );
- $_POST['_total'] = count( $this->_comments );
- $_POST['_per_page'] = 100;
- $_POST['_page'] = 1;
- $_POST['_url'] = admin_url( 'edit-comments.php' );
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'dim-comment' );
- }
-
- /**
- * Tests with a bad nonce.
- *
- * Expects test to fail.
- *
- * @param WP_Comment $comment Comment object.
- */
- public function _test_with_bad_nonce( $comment ) {
-
- // Reset request.
- $this->_clear_post_action();
-
- // Become a subscriber.
- $this->_setRole( 'administrator' );
-
- // Set up the $_POST request.
- $_POST['id'] = $comment->comment_ID;
- $_POST['_ajax_nonce'] = wp_create_nonce( uniqid() );
- $_POST['_total'] = count( $this->_comments );
- $_POST['_per_page'] = 100;
- $_POST['_page'] = 1;
- $_POST['_url'] = admin_url( 'edit-comments.php' );
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'dim-comment' );
- }
-
- /**
- * Tests with a bad ID.
- *
- * Expects test to fail.
- */
- public function test_with_bad_id() {
-
- // Reset request.
- $this->_clear_post_action();
-
- // Become a subscriber.
- $this->_setRole( 'administrator' );
-
- // Set up the $_POST request.
- $_POST['id'] = 12346789;
- $_POST['_ajax_nonce'] = wp_create_nonce( 'dim-comment_12346789' );
- $_POST['_total'] = count( $this->_comments );
- $_POST['_per_page'] = 100;
- $_POST['_page'] = 1;
- $_POST['_url'] = admin_url( 'edit-comments.php' );
-
- // Make the request, look for a timestamp in the exception.
- try {
- $this->_handleAjax( 'dim-comment' );
- $this->fail( 'Expected exception: WPAjaxDieContinueException' );
- } catch ( WPAjaxDieContinueException $e ) {
-
- // Get the response.
- $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
-
- // Ensure everything is correct.
- $this->assertSame( '0', (string) $xml->response[0]->comment['id'] );
- $this->assertSame( 'dim-comment_0', (string) $xml->response['action'] );
- $this->assertStringContainsString( 'Comment ' . $_POST['id'] . ' does not exist', $this->_last_response );
-
- } catch ( Exception $e ) {
- $this->fail( 'Unexpected exception type: ' . get_class( $e ) );
- }
- }
-
- /**
- * Dims a comment as an administrator (expects success).
- */
- public function test_ajax_comment_dim_actions_as_administrator() {
- $comment = array_pop( $this->_comments );
- $this->_test_as_admin( $comment );
- $this->_test_as_admin( $comment );
- }
-
- /**
- * Dims a comment as a subscriber (expects permission denied).
- */
- public function test_ajax_comment_dim_actions_as_subscriber() {
- $comment = array_pop( $this->_comments );
- $this->_test_as_subscriber( $comment );
- }
-
- /**
- * Dims a comment with no ID.
- */
- public function test_ajax_dim_comment_no_id() {
- $comment = array_pop( $this->_comments );
- $this->_test_as_admin( $comment );
- }
-
- /**
- * Dims a comment with a bad nonce.
- */
- public function test_ajax_dim_comment_bad_nonce() {
- $comment = array_pop( $this->_comments );
- $this->_test_with_bad_nonce( $comment );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxEditCommentphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/EditComment.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/EditComment.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/EditComment.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,244 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Ajax comment functionality.
- *
- * @package WordPress
- * @subpackage UnitTests
- * @since 3.4.0
- * @group ajax
- *
- * @covers ::wp_ajax_edit_comment
- */
-class Tests_Ajax_EditComment extends WP_Ajax_UnitTestCase {
-
- /**
- * A post with at least one comment.
- *
- * @var mixed
- */
- protected $_comment_post = null;
-
- /**
- * Sets up the test fixture.
- */
- public function set_up() {
- parent::set_up();
- $post_id = self::factory()->post->create();
- self::factory()->comment->create_post_comments( $post_id, 5 );
- $this->_comment_post = get_post( $post_id );
- }
-
- /**
- * Gets comments as a privileged user (administrator).
- *
- * Expects test to pass.
- */
- public function test_as_admin() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Get a comment.
- $comments = get_comments(
- array(
- 'post_id' => $this->_comment_post->ID,
- )
- );
- $comment = array_pop( $comments );
-
- // Set up a default request.
- $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
- $_POST['comment_ID'] = $comment->comment_ID;
- $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
-
- // Make the request.
- try {
- $this->_handleAjax( 'edit-comment' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
-
- // Check the meta data.
- $this->assertSame( '-1', (string) $xml->response[0]->edit_comment['position'] );
- $this->assertSame( $comment->comment_ID, (string) $xml->response[0]->edit_comment['id'] );
- $this->assertSame( 'edit-comment_' . $comment->comment_ID, (string) $xml->response['action'] );
-
- // Check the payload.
- $this->assertNotEmpty( (string) $xml->response[0]->edit_comment[0]->response_data );
-
- // And supplemental is empty.
- $this->assertEmpty( (string) $xml->response[0]->edit_comment[0]->supplemental );
- }
-
- /**
- * @ticket 33154
- */
- public function test_editor_can_edit_orphan_comments() {
- global $wpdb;
-
- // Become an editor.
- $this->_setRole( 'editor' );
-
- // Get a comment.
- $comments = get_comments(
- array(
- 'post_id' => $this->_comment_post->ID,
- )
- );
- $comment = array_pop( $comments );
-
- // Manually update the comment_post_ID, because wp_update_comment() will prevent it..
- $wpdb->update( $wpdb->comments, array( 'comment_post_ID' => 0 ), array( 'comment_ID' => $comment->comment_ID ) );
- clean_comment_cache( $comment->comment_ID );
-
- // Set up a default request.
- $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
- $_POST['comment_ID'] = $comment->comment_ID;
- $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
-
- // Make the request.
- try {
- $this->_handleAjax( 'edit-comment' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
-
- // Check the meta data.
- $this->assertSame( '-1', (string) $xml->response[0]->edit_comment['position'] );
- $this->assertSame( $comment->comment_ID, (string) $xml->response[0]->edit_comment['id'] );
- $this->assertSame( 'edit-comment_' . $comment->comment_ID, (string) $xml->response['action'] );
-
- // Check the payload.
- $this->assertNotEmpty( (string) $xml->response[0]->edit_comment[0]->response_data );
-
- // And supplemental is empty.
- $this->assertEmpty( (string) $xml->response[0]->edit_comment[0]->supplemental );
- }
-
- /**
- * Gets comments as a non-privileged user (subscriber).
- *
- * Expects test to fail.
- */
- public function test_as_subscriber() {
-
- // Become a subscriber.
- $this->_setRole( 'subscriber' );
-
- // Get a comment.
- $comments = get_comments(
- array(
- 'post_id' => $this->_comment_post->ID,
- )
- );
- $comment = array_pop( $comments );
-
- // Set up a default request.
- $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
- $_POST['comment_ID'] = $comment->comment_ID;
- $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'edit-comment' );
- }
-
- /**
- * Gets comments with a bad nonce.
- *
- * Expects test to fail.
- */
- public function test_bad_nonce() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Get a comment.
- $comments = get_comments(
- array(
- 'post_id' => $this->_comment_post->ID,
- )
- );
- $comment = array_pop( $comments );
-
- // Set up a default request.
- $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( uniqid() );
- $_POST['comment_ID'] = $comment->comment_ID;
- $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'get-comments' );
- }
-
- /**
- * Gets comments for an invalid post.
- *
- * This should return valid XML.
- */
- public function test_invalid_comment() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
- $_POST['comment_ID'] = 123456789;
- $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'edit-comment' );
- }
-
- /**
- * @ticket 39732
- */
- public function test_wp_update_comment_data_is_wp_error() {
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Get a comment.
- $comments = get_comments(
- array(
- 'post_id' => $this->_comment_post->ID,
- )
- );
- $comment = array_pop( $comments );
-
- // Set up a default request.
- $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
- $_POST['comment_ID'] = $comment->comment_ID;
- $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
-
- // Simulate filter check error.
- add_filter( 'wp_update_comment_data', array( $this, '_wp_update_comment_data_filter' ), 10, 3 );
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( 'wp_update_comment_data filter fails for this comment.' );
- $this->_handleAjax( 'edit-comment' );
- }
-
- /**
- * Blocks comments from being updated by returning WP_Error.
- */
- public function _wp_update_comment_data_filter( $data, $comment, $commentarr ) {
- return new WP_Error( 'comment_wrong', 'wp_update_comment_data filter fails for this comment.', 500 );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxGetCommentsphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/GetComments.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/GetComments.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/GetComments.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,160 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Ajax comment functionality.
- *
- * @package WordPress
- * @subpackage UnitTests
- * @since 3.4.0
- * @group ajax
- *
- * @covers ::wp_ajax_get_comments
- */
-class Tests_Ajax_GetComments extends WP_Ajax_UnitTestCase {
-
- /**
- * A post with at least one comment.
- *
- * @var mixed
- */
- protected static $comment_post = null;
-
- /**
- * A post with no comments.
- *
- * @var mixed
- */
- protected static $no_comment_post = null;
-
- protected static $comment_ids = array();
-
- public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
- self::$comment_post = $factory->post->create_and_get();
- self::$comment_ids = $factory->comment->create_post_comments( self::$comment_post->ID, 5 );
- self::$no_comment_post = $factory->post->create_and_get();
- }
-
- /**
- * Gets comments as a privileged user (administrator).
- *
- * Expects test to pass.
- */
- public function test_as_admin() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_POST['_ajax_nonce'] = wp_create_nonce( 'get-comments' );
- $_POST['action'] = 'get-comments';
- $_POST['p'] = self::$comment_post->ID;
-
- // Make the request.
- try {
- $this->_handleAjax( 'get-comments' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
-
- // Check the meta data.
- $this->assertSame( '1', (string) $xml->response[0]->comments['position'] );
- $this->assertSame( '0', (string) $xml->response[0]->comments['id'] );
- $this->assertSame( 'get-comments_0', (string) $xml->response['action'] );
-
- // Check the payload.
- $this->assertNotEmpty( (string) $xml->response[0]->comments[0]->response_data );
-
- // And supplemental is empty.
- $this->assertEmpty( (string) $xml->response[0]->comments[0]->supplemental );
- }
-
- /**
- * Gets comments as a non-privileged user (subscriber).
- *
- * Expects test to fail.
- */
- public function test_as_subscriber() {
-
- // Become a subscriber.
- $this->_setRole( 'subscriber' );
-
- // Set up a default request.
- $_POST['_ajax_nonce'] = wp_create_nonce( 'get-comments' );
- $_POST['action'] = 'get-comments';
- $_POST['p'] = self::$comment_post->ID;
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'get-comments' );
- }
-
- /**
- * Gets comments with a bad nonce.
- *
- * Expects test to fail.
- */
- public function test_bad_nonce() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_POST['_ajax_nonce'] = wp_create_nonce( uniqid() );
- $_POST['action'] = 'get-comments';
- $_POST['p'] = self::$comment_post->ID;
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'get-comments' );
- }
-
- /**
- * Gets comments for an invalid post.
- *
- * Bad post IDs are set to 0, this should return valid XML.
- */
- public function test_invalid_post() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_POST['_ajax_nonce'] = wp_create_nonce( 'get-comments' );
- $_POST['action'] = 'get-comments';
- $_POST['p'] = 'b0rk';
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'get-comments' );
- }
-
- /**
- * Gets comments for a post with no comments.
- */
- public function test_post_with_no_comments() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_POST['_ajax_nonce'] = wp_create_nonce( 'get-comments' );
- $_POST['action'] = 'get-comments';
- $_POST['p'] = self::$no_comment_post->ID;
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '1' );
- $this->_handleAjax( 'get-comments' );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxManageThemesphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/ManageThemes.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/ManageThemes.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/ManageThemes.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,179 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Ajax handler for instlaling, updating, and deleting themes.
- *
- * @group ajax
- *
- * @covers ::wp_ajax_update_theme
- */
-class Tests_Ajax_Manage_Themes extends WP_Ajax_UnitTestCase {
- private $orig_theme_dir;
- private $theme_root;
-
- public function set_up() {
- parent::set_up();
-
- $this->theme_root = DIR_TESTDATA . '/themedir1';
- $this->orig_theme_dir = $GLOBALS['wp_theme_directories'];
-
- // /themes is necessary as theme.php functions assume /themes is the root if there is only one root.
- $GLOBALS['wp_theme_directories'] = array( WP_CONTENT_DIR . '/themes', $this->theme_root );
-
- add_filter( 'theme_root', array( $this, 'filter_theme_root' ) );
- add_filter( 'stylesheet_root', array( $this, 'filter_theme_root' ) );
- add_filter( 'template_root', array( $this, 'filter_theme_root' ) );
-
- wp_clean_themes_cache();
- unset( $GLOBALS['wp_themes'] );
- }
-
- public function tear_down() {
- $GLOBALS['wp_theme_directories'] = $this->orig_theme_dir;
- remove_filter( 'theme_root', array( $this, 'filter_theme_root' ) );
- remove_filter( 'stylesheet_root', array( $this, 'filter_theme_root' ) );
- remove_filter( 'template_root', array( $this, 'filter_theme_root' ) );
- wp_clean_themes_cache();
- unset( $GLOBALS['wp_themes'] );
-
- parent::tear_down();
- }
-
- /**
- * Replace the normal theme root dir with our pre-made test dir.
- */
- public function filter_theme_root() {
- return $this->theme_root;
- }
-
- public function test_missing_slug() {
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
-
- // Make the request.
- try {
- $this->_handleAjax( 'update-theme' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = array(
- 'success' => false,
- 'data' => array(
- 'slug' => '',
- 'errorCode' => 'no_theme_specified',
- 'errorMessage' => 'No theme specified.',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-
- public function test_missing_capability() {
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
- $_POST['slug'] = 'foo';
-
- // Make the request.
- try {
- $this->_handleAjax( 'update-theme' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = array(
- 'success' => false,
- 'data' => array(
- 'update' => 'theme',
- 'slug' => 'foo',
- 'oldVersion' => '',
- 'newVersion' => '',
- 'errorMessage' => 'Sorry, you are not allowed to update themes for this site.',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-
- /**
- * @group ms-excluded
- */
- public function test_update_theme() {
- $this->_setRole( 'administrator' );
-
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
- $_POST['slug'] = 'twentyten';
-
- // Make the request.
- try {
-
- // Prevent wp_update_themes() from running.
- wp_installing( true );
- $this->_handleAjax( 'update-theme' );
- wp_installing( false );
-
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $theme = wp_get_theme( 'twentyten' );
- $expected = array(
- 'success' => false,
- 'data' => array(
- 'update' => 'theme',
- 'slug' => 'twentyten',
- 'oldVersion' => $theme->get( 'Version' ),
- 'newVersion' => '',
- 'debug' => array( 'The theme is at the latest version.' ),
- 'errorMessage' => 'The theme is at the latest version.',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-
- /**
- * @group ms-excluded
- */
- public function test_uppercase_theme_slug() {
- $this->_setRole( 'administrator' );
-
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
- $_POST['slug'] = 'camelCase';
-
- // Make the request.
- try {
- $this->_handleAjax( 'update-theme' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = array(
- 'success' => false,
- 'data' => array(
- 'update' => 'theme',
- 'slug' => 'camelCase',
- 'oldVersion' => '1.0',
- 'newVersion' => '',
- 'debug' => array( 'The theme is at the latest version.' ),
- 'errorMessage' => 'The theme is at the latest version.',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxMediaEditphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/MediaEdit.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/MediaEdit.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/MediaEdit.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,120 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Ajax media editing.
- *
- * @package WordPress
- * @subpackage UnitTests
- * @since 3.5.0
- * @group ajax
- *
- * @requires function imagejpeg
- */
-class Tests_Ajax_MediaEdit extends WP_Ajax_UnitTestCase {
-
- /**
- * Tear down the test fixture.
- */
- public function tear_down() {
- // Cleanup.
- $this->remove_added_uploads();
- parent::tear_down();
- }
-
- /**
- * @ticket 22985
- * @requires function imagejpeg
- *
- * @covers ::wp_insert_attachment
- * @covers ::wp_save_image
- */
- public function testCropImageThumbnail() {
- require_once ABSPATH . 'wp-admin/includes/image-edit.php';
-
- $filename = DIR_TESTDATA . '/images/canola.jpg';
- $contents = file_get_contents( $filename );
-
- $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
- $id = $this->_make_attachment( $upload );
-
- $_REQUEST['action'] = 'image-editor';
- $_REQUEST['context'] = 'edit-attachment';
- $_REQUEST['postid'] = $id;
- $_REQUEST['target'] = 'thumbnail';
- $_REQUEST['do'] = 'save';
- $_REQUEST['history'] = '[{"c":{"x":5,"y":8,"w":289,"h":322}}]';
-
- $media_meta = wp_get_attachment_metadata( $id );
- $this->assertArrayHasKey( 'sizes', $media_meta, 'attachment should have size data' );
- $this->assertArrayHasKey( 'medium', $media_meta['sizes'], 'attachment should have data for medium size' );
- $ret = wp_save_image( $id );
-
- $media_meta = wp_get_attachment_metadata( $id );
- $this->assertArrayHasKey( 'sizes', $media_meta, 'cropped attachment should have size data' );
- $this->assertArrayHasKey( 'medium', $media_meta['sizes'], 'cropped attachment should have data for medium size' );
- }
-
- /**
- * @ticket 32171
- * @requires function imagejpeg
- *
- * @covers ::wp_insert_attachment
- * @covers ::wp_save_image
- */
- public function testImageEditOverwriteConstant() {
- define( 'IMAGE_EDIT_OVERWRITE', true );
-
- require_once ABSPATH . 'wp-admin/includes/image-edit.php';
-
- $filename = DIR_TESTDATA . '/images/canola.jpg';
- $contents = file_get_contents( $filename );
-
- $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
- $id = $this->_make_attachment( $upload );
-
- $_REQUEST['action'] = 'image-editor';
- $_REQUEST['context'] = 'edit-attachment';
- $_REQUEST['postid'] = $id;
- $_REQUEST['target'] = 'all';
- $_REQUEST['do'] = 'save';
- $_REQUEST['history'] = '[{"c":{"x":5,"y":8,"w":289,"h":322}}]';
-
- $ret = wp_save_image( $id );
-
- $media_meta = wp_get_attachment_metadata( $id );
- $sizes1 = $media_meta['sizes'];
-
- $_REQUEST['history'] = '[{"c":{"x":5,"y":8,"w":189,"h":322}}]';
-
- $ret = wp_save_image( $id );
-
- $media_meta = wp_get_attachment_metadata( $id );
- $sizes2 = $media_meta['sizes'];
-
- $file_path = dirname( get_attached_file( $id ) );
-
- $files_that_should_not_exist = array();
-
- foreach ( $sizes1 as $key => $size ) {
- if ( $sizes2[ $key ]['file'] !== $size['file'] ) {
- $files_that_should_not_exist[] = $file_path . '/' . $size['file'];
- }
- }
-
- if ( ! empty( $files_that_should_not_exist ) ) {
- foreach ( $files_that_should_not_exist as $file ) {
- $this->assertFileDoesNotExist( $file, 'IMAGE_EDIT_OVERWRITE is leaving garbage image files behind.' );
- }
- } else {
- /*
- * This assertion will always pass due to the "if" condition, but prevents this test
- * from being marked as "risky" due to the test not performing any assertions.
- */
- $this->assertSame( array(), $files_that_should_not_exist );
- }
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxPrivacyErasePersonalDataphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/PrivacyErasePersonalData.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/PrivacyErasePersonalData.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/PrivacyErasePersonalData.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,839 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Testing Ajax handler for erasing personal data.
- *
- * @package WordPress\UnitTests
- * @since 5.2.0
- */
-
-/**
- * Tests_Ajax_PrivacyExportPersonalData class.
- *
- * @since 5.2.0
- *
- * @group ajax
- * @group privacy
- *
- * @covers ::wp_ajax_wp_privacy_erase_personal_data
- */
-class Tests_Ajax_PrivacyErasePersonalData extends WP_Ajax_UnitTestCase {
-
- /**
- * User Request ID.
- *
- * @since 5.2.0
- *
- * @var int $request_id
- */
- protected static $request_id;
-
- /**
- * User Request Email.
- *
- * @since 5.2.0
- *
- * @var string $request_email
- */
- protected static $request_email;
-
- /**
- * Ajax Action.
- *
- * @since 5.2.0
- *
- * @var string $action
- */
- protected static $action;
-
- /**
- * Eraser Index.
- *
- * @since 5.2.0
- *
- * @var int $eraser
- */
- protected static $eraser;
-
- /**
- * Eraser Key.
- *
- * @since 5.2.0
- *
- * @var string $eraser_key
- */
- protected static $eraser_key;
-
- /**
- * Eraser Friendly Name.
- *
- * @since 5.2.0
- *
- * @var string $eraser_friendly_name
- */
- protected static $eraser_friendly_name;
-
- /**
- * Page Index.
- *
- * @since 5.2.0
- *
- * @var int $page
- */
- protected static $page;
-
- /**
- * Last response parsed.
- *
- * @since 5.2.0
- *
- * @var array $_last_response_parsed
- */
- protected $_last_response_parsed;
-
- /**
- * An array key in the test eraser to unset.
- *
- * @since 5.2.0
- *
- * @var string $key_to_unset
- */
- protected $key_to_unset;
-
- /**
- * A value to change the test eraser callback to.
- *
- * @since 5.2.0
- *
- * @var string $new_callback_value
- */
- protected $new_callback_value;
-
- /**
- * Create user erase request fixtures.
- *
- * @param WP_UnitTest_Factory $factory Factory.
- */
- public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
- self::$request_email = 'requester@example.com';
- self::$request_id = wp_create_user_request( self::$request_email, 'remove_personal_data' );
- self::$action = 'wp-privacy-erase-personal-data';
- self::$eraser = 1;
- self::$eraser_key = 'custom-eraser';
- self::$eraser_friendly_name = 'Custom Eraser';
- self::$page = 1;
- }
-
- /**
- * Register a custom personal data eraser.
- */
- public function set_up() {
- parent::set_up();
-
- $this->key_to_unset = '';
-
- // Make sure the erasers response is not modified and avoid sending emails.
- remove_all_filters( 'wp_privacy_personal_data_erasure_page' );
- remove_all_actions( 'wp_privacy_personal_data_erased' );
-
- // Only use our custom privacy personal data eraser.
- remove_all_filters( 'wp_privacy_personal_data_erasers' );
- add_filter( 'wp_privacy_personal_data_erasers', array( $this, 'register_custom_personal_data_eraser' ) );
-
- $this->_setRole( 'administrator' );
- // `erase_others_personal_data` meta cap in Multisite installation is only granted to those with `manage_network` capability.
- if ( is_multisite() ) {
- grant_super_admin( get_current_user_id() );
- }
- }
-
- /**
- * Clean up after each test method.
- */
- public function tear_down() {
- remove_filter( 'wp_privacy_personal_data_erasers', array( $this, 'register_custom_personal_data_eraser' ) );
- $this->new_callback_value = '';
-
- if ( is_multisite() ) {
- revoke_super_admin( get_current_user_id() );
- }
-
- parent::tear_down();
- }
-
- /**
- * Helper method for changing the test eraser's callback function.
- *
- * @param string|array $callback New test eraser callback index value.
- */
- protected function _set_eraser_callback( $callback ) {
- $this->new_callback_value = $callback;
- add_filter( 'wp_privacy_personal_data_erasers', array( $this, 'filter_eraser_callback_value' ), 20 );
- }
-
- /**
- * Change the test eraser callback to a specified value.
- *
- * @since 5.2.0
- *
- * @param array $erasers List of data erasers.
- *
- * @return array Array of data erasers.
- */
- public function filter_eraser_callback_value( $erasers ) {
- $erasers[ self::$eraser_key ]['callback'] = $this->new_callback_value;
-
- return $erasers;
- }
-
- /**
- * Helper method for unsetting an array index in the test eraser.
- *
- * @param string|bool $key Test eraser key to unset.
- */
- protected function _unset_eraser_key( $key ) {
- $this->key_to_unset = $key;
- add_filter( 'wp_privacy_personal_data_erasers', array( $this, 'filter_unset_eraser_index' ), 20 );
- }
-
- /**
- * Unsets an array key in the test eraser.
- *
- * If the key is false, the eraser is set to false.
- *
- * @since 5.2.0
- *
- * @param array $erasers Erasers.
- *
- * @return array Erasers.
- */
- public function filter_unset_eraser_index( $erasers ) {
- if ( false === $this->key_to_unset ) {
- $erasers[ self::$eraser_key ] = false;
- } elseif ( ! empty( $this->key_to_unset ) ) {
- unset( $erasers[ self::$eraser_key ][ $this->key_to_unset ] );
- }
-
- return $erasers;
- }
-
- /**
- * Helper method for erasing a key from the eraser response.
- *
- * @since 5.2.0
- *
- * @param array $key Response key to unset.
- */
- protected function _unset_response_key( $key ) {
- $this->key_to_unset = $key;
- $this->_set_eraser_callback( array( $this, 'filter_unset_response_index' ) );
- }
-
- /**
- * Unsets an array index in a response.
- *
- * @since 5.2.0
- *
- * @param string $email_address The requester's email address.
- * @param int $page Page number.
- *
- * @return array Export data.
- */
- public function filter_unset_response_index( $email_address, $page = 1 ) {
- $response = $this->callback_personal_data_eraser( $email_address, $page );
-
- if ( ! empty( $this->key_to_unset ) ) {
- unset( $response[ $this->key_to_unset ] );
- }
-
- return $response;
- }
-
- /**
- * The function should send an error when the request ID is missing.
- *
- * @since 5.2.0
- *
- * @ticket 43438
- */
- public function test_error_when_missing_request_id() {
- $this->assertNotWPError( self::$request_id );
-
- // Set up a request.
- $this->_make_ajax_call(
- array(
- 'id' => null, // Missing request ID.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Missing request ID.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the request ID is less than 1.
- *
- * @since 5.2.0
- *
- * @ticket 43438
- */
- public function test_error_when_request_id_invalid() {
- $this->assertNotWPError( self::$request_id );
-
- // Set up a request.
- $this->_make_ajax_call(
- array(
- 'id' => -1, // Invalid request ID.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Invalid request ID.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the current user is missing required capabilities.
- *
- * @since 5.2.0
- *
- * @ticket 43438
- */
- public function test_error_when_current_user_missing_required_capabilities() {
- $this->_setRole( 'author' );
-
- $this->assertFalse( current_user_can( 'erase_others_personal_data' ) );
- $this->assertFalse( current_user_can( 'delete_users' ) );
-
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Sorry, you are not allowed to perform this action.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * Test requests do not succeed on multisite when the current user is not a network admin.
- *
- * @ticket 43438
- * @group multisite
- * @group ms-required
- */
- public function test_error_when_current_user_missing_required_capabilities_multisite() {
- revoke_super_admin( get_current_user_id() );
-
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Sorry, you are not allowed to perform this action.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the nonce does not validate.
- *
- * @since 5.2.0
- */
- public function test_failure_with_invalid_nonce() {
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
-
- $this->_make_ajax_call(
- array(
- 'security' => 'invalid-nonce',
- )
- );
- }
-
- /**
- * The function should send an error when the request type is incorrect.
- *
- * @since 5.2.0
- */
- public function test_error_when_incorrect_request_type() {
- $request_id = wp_create_user_request(
- 'export-request@example.com',
- 'export_personal_data' // Incorrect request type, expects 'remove_personal_data'.
- );
-
- $this->_make_ajax_call(
- array(
- 'security' => wp_create_nonce( 'wp-privacy-erase-personal-data-' . $request_id ),
- 'id' => $request_id,
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Invalid request type.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the request email is invalid.
- *
- * @since 5.2.0
- */
- public function test_error_when_invalid_email() {
- wp_update_post(
- array(
- 'ID' => self::$request_id,
- 'post_title' => '', // Invalid requester's email address.
- )
- );
-
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Invalid email address in request.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the eraser index is missing.
- *
- * @since 5.2.0
- */
- public function test_error_when_missing_eraser_index() {
- $this->_make_ajax_call(
- array(
- 'eraser' => null, // Missing eraser index.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Missing eraser index.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the page index is missing.
- *
- * @since 5.2.0
- */
- public function test_error_when_missing_page_index() {
- $this->_make_ajax_call(
- array(
- 'page' => null, // Missing page index.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Missing page index.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the eraser index is negative.
- *
- * @since 5.2.0
- */
- public function test_error_when_negative_eraser_index() {
- $this->_make_ajax_call(
- array(
- 'eraser' => -1, // Negative eraser index.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Eraser index cannot be less than one.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the eraser index is out of range.
- *
- * @since 5.2.0
- */
- public function test_error_when_eraser_index_out_of_range() {
- $this->_make_ajax_call(
- array(
- 'eraser' => PHP_INT_MAX, // Out of range eraser index.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Eraser index is out of range.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the page index is less than one.
- *
- * @since 5.2.0
- */
- public function test_error_when_page_index_less_than_one() {
- $this->_make_ajax_call(
- array(
- 'page' => 0, // Page index less than one.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Page index cannot be less than one.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when an eraser is not an array.
- *
- * @since 5.2.0
- */
- public function test_error_when_eraser_not_array() {
- $this->_unset_eraser_key( false );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected an array describing the eraser at index %s.',
- self::$eraser
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * The function should send an error when an eraser is missing a friendly name.
- *
- * @since 5.2.0
- */
- public function test_error_when_eraser_missing_friendly_name() {
- $this->_unset_eraser_key( 'eraser_friendly_name' );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Eraser array at index %s does not include a friendly name.',
- self::$eraser
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * The function should send an error when an eraser is missing a callback.
- *
- * @since 5.2.0
- */
- public function test_error_when_eraser_missing_callback() {
- $this->_unset_eraser_key( 'callback' );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Eraser does not include a callback: %s.',
- self::$eraser_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * The function should send an error when an eraser, at a given index, has an invalid callback.
- *
- * @since 5.2.0
- */
- public function test_error_when_eraser_index_invalid_callback() {
- $this->_set_eraser_callback( false );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Eraser callback is not valid: %s.',
- self::$eraser_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * The function should send an error when an eraser, at a given index, is missing an array response.
- *
- * @since 5.2.0
- */
- public function test_error_when_eraser_index_invalid_response() {
- $this->_set_eraser_callback( '__return_null' );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Did not receive array from %1$s eraser (index %2$d).',
- self::$eraser_friendly_name,
- self::$eraser
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * The function should send an error when missing an items_removed index.
- *
- * @since 5.2.0
- */
- public function test_error_when_eraser_items_removed_missing() {
- $this->_unset_response_key( 'items_removed' );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected items_removed key in response array from %1$s eraser (index %2$d).',
- self::$eraser_friendly_name,
- self::$eraser
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * The function should send an error when missing an items_retained index.
- *
- * @since 5.2.0
- */
- public function test_error_when_eraser_items_retained_missing() {
- $this->_unset_response_key( 'items_retained' );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected items_retained key in response array from %1$s eraser (index %2$d).',
- self::$eraser_friendly_name,
- self::$eraser
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * The function should send an error when missing a messages index.
- *
- * @since 5.2.0
- */
- public function test_error_when_eraser_messages_missing() {
- $this->_unset_response_key( 'messages' );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected messages key in response array from %1$s eraser (index %2$d).',
- self::$eraser_friendly_name,
- self::$eraser
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * The function should send an error when the messages index is not an array.
- *
- * @since 5.2.0
- */
- public function test_error_when_eraser_messages_not_array() {
- $this->_set_eraser_callback( array( $this, 'filter_response_messages_invalid' ) );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected messages key to reference an array in response array from %1$s eraser (index %2$d).',
- self::$eraser_friendly_name,
- self::$eraser
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * Change the messages index to an invalid value (not an array).
- *
- * @since 5.2.0
- *
- * @param string $email_address The requester's email address.
- * @param int $page Page number.
- *
- * @return array Export data.
- */
- public function filter_response_messages_invalid( $email_address, $page = 1 ) {
- $response = $this->callback_personal_data_eraser( $email_address, $page );
- $response['messages'] = true;
-
- return $response;
- }
-
- /**
- * The function should send an error when an eraser is missing 'done' in array response.
- *
- * @since 5.2.0
- */
- public function test_error_when_eraser_missing_done_response() {
- $this->_unset_response_key( 'done' );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected done flag in response array from %1$s eraser (index %2$d).',
- self::$eraser_friendly_name,
- self::$eraser
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * The function should successfully send erasers response data when the current user has the required
- * capabilities.
- *
- * @since 5.2.0
- *
- * @ticket 43438
- */
- public function test_success_when_current_user_has_required_capabilities() {
- $this->assertTrue( current_user_can( 'erase_others_personal_data' ) );
- $this->assertTrue( current_user_can( 'delete_users' ) );
-
- $this->_make_ajax_call();
-
- $this->assertSame(
- sprintf( 'A message regarding retained data for %s.', self::$request_email ),
- $this->_last_response_parsed['data']['messages'][0]
- );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertTrue( $this->_last_response_parsed['data']['items_removed'] );
- $this->assertTrue( $this->_last_response_parsed['data']['items_retained'] );
- $this->assertTrue( $this->_last_response_parsed['data']['done'] );
- }
-
- /**
- * The function should successfully send erasers response data when no items to erase.
- *
- * @since 5.2.0
- *
- * @ticket 43438
- */
- public function test_success_when_no_items_to_erase() {
-
- $this->_make_ajax_call( array( 'page' => 2 ) );
-
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertFalse( $this->_last_response_parsed['data']['items_removed'] );
- $this->assertFalse( $this->_last_response_parsed['data']['items_retained'] );
- $this->assertEmpty( $this->_last_response_parsed['data']['messages'] );
- $this->assertTrue( $this->_last_response_parsed['data']['done'] );
- }
-
- /**
- * Test that the function's output should be filterable with the `wp_privacy_personal_data_erasure_page` filter.
- *
- * @since 5.2.0
- */
- public function test_output_should_be_filterable() {
- add_filter( 'wp_privacy_personal_data_erasure_page', array( $this, 'filter_eraser_data_response' ), 20, 6 );
- $this->_make_ajax_call();
-
- $expected_new_index = self::$request_email . '-' . self::$request_id . '-' . self::$eraser_key;
-
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertSame( 'filtered removed', $this->_last_response_parsed['data']['items_removed'] );
- $this->assertSame( 'filtered retained', $this->_last_response_parsed['data']['items_retained'] );
- $this->assertSame( array( 'filtered messages' ), $this->_last_response_parsed['data']['messages'] );
- $this->assertSame( 'filtered done', $this->_last_response_parsed['data']['done'] );
- $this->assertSame( $expected_new_index, $this->_last_response_parsed['data']['new_index'] );
- }
-
- /**
- * Filters the eraser response.
- *
- * @since 5.2.0
- *
- * @param array $response The personal data for the given eraser and page.
- * @param int $eraser_index The index of the eraser that provided this data.
- * @param string $email_address The email address associated with this personal data.
- * @param int $page The page for this response.
- * @param int $request_id The privacy request post ID associated with this request.
- * @param string $eraser_key The key (slug) of the eraser that provided this data.
- *
- * @return array Filtered erase response.
- */
- public function filter_eraser_data_response( $response, $eraser_index, $email_address, $page, $request_id, $eraser_key ) {
- $response['items_removed'] = 'filtered removed';
- $response['items_retained'] = 'filtered retained';
- $response['messages'] = array( 'filtered messages' );
- $response['done'] = 'filtered done';
- $response['new_index'] = $email_address . '-' . $request_id . '-' . $eraser_key;
-
- return $response;
- }
-
- /**
- * Register handler for a custom personal data eraser.
- *
- * @since 5.2.0
- *
- * @param array $erasers An array of personal data erasers.
- *
- * @return array An array of personal data erasers.
- */
- public function register_custom_personal_data_eraser( $erasers ) {
- $erasers[ self::$eraser_key ] = array(
- 'eraser_friendly_name' => self::$eraser_friendly_name,
- 'callback' => array( $this, 'callback_personal_data_eraser' ),
- );
- return $erasers;
- }
-
- /**
- * Custom Personal Data Eraser.
- *
- * @since 5.2.0
- *
- * @param string $email_address The comment author email address.
- * @param int $page Page number.
- *
- * @return array Erase data.
- */
- public function callback_personal_data_eraser( $email_address, $page = 1 ) {
- if ( 1 === $page ) {
- return array(
- 'items_removed' => true,
- 'items_retained' => true,
- 'messages' => array( sprintf( 'A message regarding retained data for %s.', $email_address ) ),
- 'done' => true,
- );
- }
-
- return array(
- 'items_removed' => false,
- 'items_retained' => false,
- 'messages' => array(),
- 'done' => true,
- );
- }
-
- /**
- * Helper function for Ajax handler.
- *
- * @since 5.2.0
- *
- * @param array $args Ajax request arguments.
- */
- protected function _make_ajax_call( $args = array() ) {
- $this->_last_response_parsed = null;
- $this->_last_response = '';
-
- $defaults = array(
- 'action' => self::$action,
- 'security' => wp_create_nonce( self::$action . '-' . self::$request_id ),
- 'page' => self::$page,
- 'id' => self::$request_id,
- 'eraser' => self::$eraser,
- );
-
- $_POST = wp_parse_args( $args, $defaults );
-
- try {
- $this->_handleAjax( self::$action );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- if ( $this->_last_response ) {
- $this->_last_response_parsed = json_decode( $this->_last_response, true );
- }
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxPrivacyExportPersonalDataphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/PrivacyExportPersonalData.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/PrivacyExportPersonalData.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/PrivacyExportPersonalData.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,842 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Testing Ajax handler for exporting personal data.
- *
- * @package WordPress\UnitTests
- * @since 5.2.0
- */
-
-/**
- * Tests_Ajax_PrivacyExportPersonalData class.
- *
- * @since 5.2.0
- *
- * @group ajax
- * @group privacy
- *
- * @covers ::wp_ajax_wp_privacy_export_personal_data
- */
-class Tests_Ajax_PrivacyExportPersonalData extends WP_Ajax_UnitTestCase {
-
- /**
- * User Request ID.
- *
- * @since 5.2.0
- *
- * @var int $request_id
- */
- protected static $request_id;
-
- /**
- * User Request Email.
- *
- * @since 5.2.0
- *
- * @var string $request_email
- */
- protected static $request_email;
-
- /**
- * Ajax Action.
- *
- * @since 5.2.0
- *
- * @var string $action
- */
- protected static $action;
-
- /**
- * Exporter Index.
- *
- * @since 5.2.0
- *
- * @var int $exporter
- */
- protected static $exporter;
-
- /**
- * Exporter Key.
- *
- * @since 5.2.0
- *
- * @var string $exporter_key
- */
- protected static $exporter_key;
-
- /**
- * Exporter Friendly Name.
- *
- * @since 5.2.0
- *
- * @var string $exporter_friendly_name
- */
- protected static $exporter_friendly_name;
-
- /**
- * Page Index.
- *
- * @since 5.2.0
- *
- * @var int $page
- */
- protected static $page;
-
- /**
- * Send As Email.
- *
- * @since 5.2.0
- *
- * @var bool $send_as_email
- */
- protected static $send_as_email;
-
- /**
- * Last response parsed.
- *
- * @since 5.2.0
- *
- * @var array $_last_response_parsed
- */
- protected $_last_response_parsed;
-
- /**
- * An array key in the test exporter to unset.
- *
- * @since 5.2.0
- *
- * @var string $key_to_unset
- */
- protected $key_to_unset;
-
- /**
- * A value to change the test exporter callback to.
- *
- * @since 5.2.0
- *
- * @var string $new_callback_value
- */
- protected $new_callback_value;
-
- /**
- * Create user export request fixtures.
- *
- * @since 5.2.0
- *
- * @param WP_UnitTest_Factory $factory Factory.
- */
- public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
- self::$request_email = 'requester@example.com';
- self::$request_id = wp_create_user_request( self::$request_email, 'export_personal_data' );
- self::$action = 'wp-privacy-export-personal-data';
- self::$exporter = 1;
- self::$exporter_key = 'custom-exporter';
- self::$exporter_friendly_name = 'Custom Exporter';
- self::$page = 1;
- self::$send_as_email = false;
- }
-
- /**
- * Setup before each test method.
- *
- * @since 5.2.0
- */
- public function set_up() {
- parent::set_up();
-
- $this->key_to_unset = '';
- $this->new_callback_value = '';
-
- // Make sure the exporter response is not modified and avoid e.g. writing export file to disk.
- remove_all_filters( 'wp_privacy_personal_data_export_page' );
-
- // Only use our custom privacy personal data exporter.
- remove_all_filters( 'wp_privacy_personal_data_exporters' );
- add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'filter_register_custom_personal_data_exporter' ) );
-
- $this->_setRole( 'administrator' );
- // `export_others_personal_data` meta cap in Multisite installation is only granted to those with `manage_network` capability.
- if ( is_multisite() ) {
- grant_super_admin( get_current_user_id() );
- }
- }
-
- /**
- * Clean up after each test method.
- */
- public function tear_down() {
- remove_filter( 'wp_privacy_personal_data_exporters', array( $this, 'filter_register_custom_personal_data_exporter' ) );
-
- if ( is_multisite() ) {
- revoke_super_admin( get_current_user_id() );
- }
- parent::tear_down();
- }
-
- /**
- * Helper method for changing the test exporter's callback function.
- *
- * @param string|array $callback New test exporter callback function.
- */
- protected function _set_exporter_callback( $callback ) {
- $this->new_callback_value = $callback;
- add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'filter_exporter_callback_value' ), 20 );
- }
-
- /**
- * Change the test exporter callback to a specified value.
- *
- * @since 5.2.0
- *
- * @param array $exporters List of data exporters.
- * @return array List of data exporters.
- */
- public function filter_exporter_callback_value( $exporters ) {
- $exporters[ self::$exporter_key ]['callback'] = $this->new_callback_value;
-
- return $exporters;
- }
-
- /**
- * Helper method for unsetting an array index in the test exporter.
- *
- * @param string $key Test exporter key to unset.
- */
- protected function _unset_exporter_key( $key ) {
- $this->key_to_unset = $key;
- add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'filter_unset_exporter_key' ), 20 );
- }
-
- /**
- * Unset a specified key in the test exporter array.
- *
- * @param array $exporters List of data exporters.
- *
- * @return array List of data exporters.
- */
- public function filter_unset_exporter_key( $exporters ) {
- if ( false === $this->key_to_unset ) {
- $exporters[ self::$exporter_key ] = false;
- } elseif ( ! empty( $this->key_to_unset ) ) {
- unset( $exporters[ self::$exporter_key ][ $this->key_to_unset ] );
- }
-
- return $exporters;
- }
-
- /**
- * The function should send an error when the request ID is missing.
- *
- * @since 5.2.0
- */
- public function test_error_when_missing_request_id() {
- $this->_make_ajax_call(
- array(
- 'id' => null, // Missing request ID.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Missing request ID.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the request ID is less than 1.
- *
- * @since 5.2.0
- */
- public function test_error_when_invalid_id() {
- $this->_make_ajax_call(
- array(
- 'id' => -1, // Invalid request ID, less than 1.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Invalid request ID.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the current user is missing the required capability.
- *
- * @since 5.2.0
- */
- public function test_error_when_current_user_missing_required_capability() {
- $this->_setRole( 'author' );
-
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertFalse( current_user_can( 'export_others_personal_data' ) );
- $this->assertSame( 'Sorry, you are not allowed to perform this action.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * Test requests do not succeed on multisite when the current user is not a network admin.
- *
- * @ticket 43438
- * @group multisite
- * @group ms-required
- */
- public function test_error_when_current_user_missing_required_capability_multisite() {
- revoke_super_admin( get_current_user_id() );
-
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Sorry, you are not allowed to perform this action.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the nonce does not validate.
- *
- * @since 5.2.0
- */
- public function test_failure_with_invalid_nonce() {
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
-
- $this->_make_ajax_call(
- array(
- 'security' => 'invalid-nonce',
- )
- );
- }
-
- /**
- * The function should send an error when the request type is incorrect.
- *
- * @since 5.2.0
- */
- public function test_error_when_incorrect_request_type() {
- $request_id = wp_create_user_request(
- 'erase-request@example.com',
- 'remove_personal_data' // Incorrect request type, expects 'export_personal_data'.
- );
-
- $this->_make_ajax_call(
- array(
- 'security' => wp_create_nonce( 'wp-privacy-export-personal-data-' . $request_id ),
- 'id' => $request_id,
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Invalid request type.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the requester's email address is invalid.
- *
- * @since 5.2.0
- */
- public function test_error_when_invalid_email_address() {
- wp_update_post(
- array(
- 'ID' => self::$request_id,
- 'post_title' => '', // Invalid requester's email address.
- )
- );
-
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'A valid email address must be given.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the exporter index is missing.
- *
- * @since 5.2.0
- */
- public function test_error_when_missing_exporter_index() {
- $this->_make_ajax_call(
- array(
- 'exporter' => null, // Missing exporter index.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Missing exporter index.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the page index is missing.
- *
- * @since 5.2.0
- */
- public function test_error_when_missing_page_index() {
- $this->_make_ajax_call(
- array(
- 'page' => null, // Missing page index.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Missing page index.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when an exporter has improperly used the `wp_privacy_personal_data_exporters` filter.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_has_improperly_used_exporters_filter() {
- // Improper filter usage: returns false instead of an expected array.
- add_filter( 'wp_privacy_personal_data_exporters', '__return_false', 999 );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'An exporter has improperly used the registration filter.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the exporter index is negative.
- *
- * @since 5.2.0
- */
- public function test_error_when_negative_exporter_index() {
- $this->_make_ajax_call(
- array(
- 'exporter' => -1, // Negative exporter index.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Exporter index cannot be negative.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the exporter index is out of range.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_index_out_of_range() {
- $this->_make_ajax_call(
- array(
- 'exporter' => PHP_INT_MAX, // Out of range exporter index.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Exporter index is out of range.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when the page index is less than one.
- *
- * @since 5.2.0
- */
- public function test_error_when_page_index_less_than_one() {
- $this->_make_ajax_call(
- array(
- 'page' => 0, // Page index less than one.
- )
- );
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Page index cannot be less than one.', $this->_last_response_parsed['data'] );
- }
-
- /**
- * The function should send an error when an exporter is not an array.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_not_array() {
- $this->_unset_exporter_key( false );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected an array describing the exporter at index %s.',
- self::$exporter_key
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * The function should send an error when an exporter is missing a friendly name.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_missing_friendly_name() {
- $this->_unset_exporter_key( 'exporter_friendly_name' );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Exporter array at index %s does not include a friendly name.',
- self::$exporter_key
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * The function should send an error when an exporter is missing a callback.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_missing_callback() {
- $this->_unset_exporter_key( 'callback' );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Exporter does not include a callback: %s.',
- self::$exporter_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * The function should send an error when an exporter, at a given index, has an invalid callback.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_index_invalid_callback() {
- $this->_set_exporter_callback( false );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Exporter callback is not a valid callback: %s.',
- self::$exporter_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * When an exporter callback returns a WP_Error, it should be passed as the error.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_callback_returns_wp_error() {
- $this->_set_exporter_callback( array( $this, 'callback_return_wp_error' ) );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'passed_message', $this->_last_response_parsed['data'][0]['code'] );
- $this->assertSame( 'This is a WP_Error message.', $this->_last_response_parsed['data'][0]['message'] );
- }
-
- /**
- * Callback for exporter's response.
- *
- * @since 5.2.0
- *
- * @param string $email_address The requester's email address.
- * @param int $page Page number.
- * @return WP_Error WP_Error instance.
- */
- public function callback_return_wp_error( $email_address, $page = 1 ) {
- return new WP_Error( 'passed_message', 'This is a WP_Error message.' );
- }
-
- /**
- * The function should send an error when an exporter, at a given index, is missing an array response.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_index_invalid_response() {
- $this->_set_exporter_callback( '__return_null' );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected response as an array from exporter: %s.',
- self::$exporter_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * The function should send an error when an exporter is missing data in array response.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_missing_data_response() {
- $this->_set_exporter_callback( array( $this, 'callback_missing_data_response' ) );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected data in response array from exporter: %s.',
- self::$exporter_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * Callback for exporter's response.
- *
- * @since 5.2.0
- *
- * @param string $email_address The requester's email address.
- * @param int $page Page number.
- *
- * @return array Export data.
- */
- public function callback_missing_data_response( $email_address, $page = 1 ) {
- $response = $this->callback_custom_personal_data_exporter( $email_address, $page );
- unset( $response['data'] ); // Missing data part of response.
-
- return $response;
- }
-
- /**
- * The function should send an error when an exporter is missing 'data' array in array response.
- *
- * @since 5.2.0
- */
- public function test_function_should_error_when_exporter_missing_data_array_response() {
- $this->_set_exporter_callback( array( $this, 'callback_missing_data_array_response' ) );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected data array in response array from exporter: %s.',
- self::$exporter_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * Callback for exporter's response.
- *
- * @since 5.2.0
- *
- * @param string $email_address The requester's email address.
- * @param int $page Page number.
- *
- * @return array Export data.
- */
- public function callback_missing_data_array_response( $email_address, $page = 1 ) {
- $response = $this->callback_custom_personal_data_exporter( $email_address, $page );
- $response['data'] = false; // Not an array.
- return $response;
- }
-
- /**
- * The function should send an error when an exporter is missing 'done' in array response.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_missing_done_response() {
- $this->_set_exporter_callback( array( $this, 'callback_missing_done_response' ) );
- $this->_make_ajax_call();
-
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected done (boolean) in response array from exporter: %s.',
- self::$exporter_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
-
- /**
- * Remove the response's done flag.
- *
- * @since 5.2.0
- *
- * @param string $email_address The requester's email address.
- * @param int $page Page number.
- *
- * @return array Export data.
- */
- public function callback_missing_done_response( $email_address, $page = 1 ) {
- $response = $this->callback_custom_personal_data_exporter( $email_address, $page );
- unset( $response['done'] );
-
- return $response;
- }
-
- /**
- * The function should successfully send exporter data response when the current user has the required capability.
- *
- * @since 5.2.0
- */
- public function test_succeeds_when_current_user_has_required_capability() {
- $this->assertTrue( current_user_can( 'export_others_personal_data' ) );
-
- $this->_make_ajax_call();
-
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertSame( 'custom-exporter-item-id', $this->_last_response_parsed['data']['data']['item_id'] );
- $this->assertSame( 'Email', $this->_last_response_parsed['data']['data']['data'][0]['name'] );
- $this->assertSame( self::$request_email, $this->_last_response_parsed['data']['data']['data'][0]['value'] );
- }
-
- /**
- * The function should successfully send exporter data response when no items to export.
- *
- * @since 5.2.0
- */
- public function test_success_when_no_items_to_export() {
-
- $this->_make_ajax_call( array( 'page' => 2 ) );
-
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertEmpty( $this->_last_response_parsed['data']['data'] );
- $this->assertTrue( $this->_last_response_parsed['data']['done'] );
- }
-
- /**
- * The function's output should be filterable with the `wp_privacy_personal_data_export_page` filter.
- *
- * @since 5.2.0
- */
- public function test_output_should_be_filterable() {
- add_filter( 'wp_privacy_personal_data_export_page', array( $this, 'filter_exporter_data_response' ), 20, 7 );
- $this->_make_ajax_call();
-
- $expected_group_label = sprintf(
- '%s-%s-%s-%s-%s-%s',
- self::$exporter,
- self::$page,
- self::$request_email,
- self::$request_id,
- self::$send_as_email,
- self::$exporter_key
- );
-
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertSame( $expected_group_label, $this->_last_response_parsed['data']['group_label'] );
- $this->assertSame( 'filtered_group_id', $this->_last_response_parsed['data']['group_id'] );
- $this->assertSame( 'filtered_item_id', $this->_last_response_parsed['data']['item_id'] );
- $this->assertSame( 'filtered_name', $this->_last_response_parsed['data']['data'][0]['name'] );
- $this->assertSame( 'filtered_value', $this->_last_response_parsed['data']['data'][0]['value'] );
- }
-
- /**
- * Filter exporter's data response.
- *
- * @since 5.2.0
- *
- * @param array $response The personal data for the given exporter and page.
- * @param int $exporter_index The index of the exporter that provided this data.
- * @param string $email_address The email address associated with this personal data.
- * @param int $page The page for this response.
- * @param int $request_id The privacy request post ID associated with this request.
- * @param bool $send_as_email Whether the final results of the export should be emailed to the user.
- * @param string $exporter_key The key (slug) of the exporter that provided this data.
- *
- * @return array The personal data for the given exporter and page.
- */
- public function filter_exporter_data_response( $response, $exporter_index, $email_address, $page, $request_id, $send_as_email, $exporter_key ) {
- $group_label = sprintf(
- '%s-%s-%s-%s-%s-%s',
- $exporter_index,
- $page,
- $email_address,
- $request_id,
- $send_as_email,
- $exporter_key
- );
- $response['group_label'] = $group_label;
- $response['group_id'] = 'filtered_group_id';
- $response['item_id'] = 'filtered_item_id';
- $response['data'][0]['name'] = 'filtered_name';
- $response['data'][0]['value'] = 'filtered_value';
-
- return $response;
- }
-
- /**
- * Filter to register a custom personal data exporter.
- *
- * @since 5.2.0
- *
- * @param array $exporters An array of personal data exporters.
- *
- * @return array An array of personal data exporters.
- */
- public function filter_register_custom_personal_data_exporter( $exporters ) {
- $exporters[ self::$exporter_key ] = array(
- 'exporter_friendly_name' => self::$exporter_friendly_name,
- 'callback' => array( $this, 'callback_custom_personal_data_exporter' ),
- );
- return $exporters;
- }
-
- /**
- * Callback for a custom personal data exporter.
- *
- * @since 5.2.0
- *
- * @param string $email_address The requester's email address.
- * @param int $page Page number.
- *
- * @return array Export data response.
- */
- public function callback_custom_personal_data_exporter( $email_address, $page = 1 ) {
- $data_to_export = array();
-
- if ( 1 === $page ) {
- $data_to_export = array(
- 'group_id' => self::$exporter_key . '-group-id',
- 'group_label' => self::$exporter_key . '-group-label',
- 'item_id' => self::$exporter_key . '-item-id',
- 'data' => array(
- array(
- 'name' => 'Email',
- 'value' => $email_address,
- ),
- ),
- );
- }
-
- return array(
- 'data' => $data_to_export,
- 'done' => true,
- );
- }
-
- /**
- * Helper function for Ajax handler.
- *
- * @since 5.2.0
- *
- * @param array $args Ajax request arguments.
- */
- protected function _make_ajax_call( $args = array() ) {
- $this->_last_response_parsed = null;
- $this->_last_response = '';
-
- $defaults = array(
- 'action' => self::$action,
- 'security' => wp_create_nonce( self::$action . '-' . self::$request_id ),
- 'exporter' => self::$exporter,
- 'page' => self::$page,
- 'sendAsEmail' => self::$send_as_email,
- 'id' => self::$request_id,
- );
-
- $_POST = wp_parse_args( $args, $defaults );
-
- try {
- $this->_handleAjax( self::$action );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- if ( $this->_last_response ) {
- $this->_last_response_parsed = json_decode( $this->_last_response, true );
- }
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxQuickEditphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/QuickEdit.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/QuickEdit.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/QuickEdit.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,89 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Quick Edit AJAX functionality.
- *
- * @group ajax
- */
-class Tests_Ajax_QuickEdit extends WP_Ajax_UnitTestCase {
-
- /**
- * @ticket 26948
- *
- * @covers ::wp_ajax_inline_save
- * @covers ::edit_post
- */
- public function test_dont_process_terms_if_taxonomy_does_not_allow_show_on_quick_edit() {
- register_taxonomy(
- 'wptests_tax_1',
- 'post',
- array(
- 'show_in_quick_edit' => false,
- 'hierarchical' => true,
- )
- );
- register_taxonomy(
- 'wptests_tax_2',
- 'post',
- array(
- 'show_in_quick_edit' => true,
- 'hierarchical' => true,
- )
- );
-
- $t1 = self::factory()->term->create(
- array(
- 'taxonomy' => 'wptests_tax_1',
- )
- );
- $t2 = self::factory()->term->create(
- array(
- 'taxonomy' => 'wptests_tax_2',
- )
- );
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- $post = self::factory()->post->create_and_get(
- array(
- 'post_author' => get_current_user_id(),
- )
- );
-
- // Set up a request.
- $_POST['_inline_edit'] = wp_create_nonce( 'inlineeditnonce' );
- $_POST['post_ID'] = $post->ID;
- $_POST['post_type'] = $post->post_type;
- $_POST['content'] = $post->post_content;
- $_POST['excerpt'] = $post->post_excerpt;
- $_POST['_status'] = $post->post_status;
- $_POST['post_status'] = $post->post_status;
- $_POST['screen'] = 'post';
- $_POST['post_view'] = 'excerpt';
- $_POST['tax_input'] = array(
- 'wptests_tax_1' => array( $t1 ),
- 'wptests_tax_2' => array( $t2 ),
- );
-
- // Make the request.
- try {
- $this->_handleAjax( 'inline-save' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // 'wptests_tax_1' terms should have been refused.
- $post_terms_1 = wp_get_object_terms( $post->ID, 'wptests_tax_1' );
- $this->assertEmpty( $post_terms_1 );
-
- // 'wptests_tax_2' terms should have been added successfully.
- $post_terms_2 = wp_get_object_terms( $post->ID, 'wptests_tax_2' );
- $this->assertSameSets( array( $t2 ), wp_list_pluck( $post_terms_2, 'term_id' ) );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxReplytoCommentphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/ReplytoComment.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/ReplytoComment.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/ReplytoComment.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,272 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Ajax comment functionality.
- *
- * @package WordPress
- * @subpackage UnitTests
- * @since 3.4.0
- * @group ajax
- *
- * @covers ::wp_ajax_replyto_comment
- */
-class Tests_Ajax_ReplytoComment extends WP_Ajax_UnitTestCase {
-
- /**
- * A post with at least one comment.
- *
- * @var mixed
- */
- protected static $comment_post = null;
-
- /**
- * Draft post.
- *
- * @var mixed
- */
- protected static $draft_post = null;
-
- protected static $comment_ids = array();
-
- public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
- self::$comment_post = $factory->post->create_and_get();
- self::$comment_ids = $factory->comment->create_post_comments( self::$comment_post->ID, 5 );
- self::$draft_post = $factory->post->create_and_get( array( 'post_status' => 'draft' ) );
- }
-
- public function tear_down() {
- remove_filter( 'query', array( $this, '_block_comments' ) );
- parent::tear_down();
- }
-
- /**
- * Tests reply as a privileged user (administrator).
- *
- * Expects test to pass.
- */
- public function test_as_admin() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Get a comment.
- $comments = get_comments(
- array(
- 'post_id' => self::$comment_post->ID,
- )
- );
- $comment = array_pop( $comments );
-
- // Set up a default request.
- $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
- $_POST['comment_ID'] = $comment->comment_ID;
- $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
- $_POST['comment_post_ID'] = self::$comment_post->ID;
-
- // Make the request.
- try {
- $this->_handleAjax( 'replyto-comment' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
-
- // Check the meta data.
- $this->assertSame( '-1', (string) $xml->response[0]->comment['position'] );
- $this->assertGreaterThan( 0, (int) $xml->response[0]->comment['id'] );
- $this->assertNotEmpty( (string) $xml->response['action'] );
-
- // Check the payload.
- $this->assertNotEmpty( (string) $xml->response[0]->comment[0]->response_data );
-
- // And supplemental is empty.
- $this->assertEmpty( (string) $xml->response[0]->comment[0]->supplemental );
- }
-
- /**
- * Tests reply as a non-privileged user (subscriber).
- *
- * Expects test to fail.
- */
- public function test_as_subscriber() {
-
- // Become an administrator.
- $this->_setRole( 'subscriber' );
-
- // Get a comment.
- $comments = get_comments(
- array(
- 'post_id' => self::$comment_post->ID,
- )
- );
- $comment = array_pop( $comments );
-
- // Set up a default request.
- $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
- $_POST['comment_ID'] = $comment->comment_ID;
- $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
- $_POST['comment_post_ID'] = self::$comment_post->ID;
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'replyto-comment' );
- }
-
- /**
- * Tests reply using a bad nonce.
- *
- * Expects test to fail.
- */
- public function test_bad_nonce() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Get a comment.
- $comments = get_comments(
- array(
- 'post_id' => self::$comment_post->ID,
- )
- );
- $comment = array_pop( $comments );
-
- // Set up a default request.
- $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( uniqid() );
- $_POST['comment_ID'] = $comment->comment_ID;
- $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
- $_POST['comment_post_ID'] = self::$comment_post->ID;
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'replyto-comment' );
- }
-
- /**
- * Tests reply to an invalid post.
- *
- * Expects test to fail.
- */
- public function test_invalid_post() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
- $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
- $_POST['comment_post_ID'] = 123456789;
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'replyto-comment' );
- }
-
- /**
- * Tests reply to a draft post.
- *
- * Expects test to fail.
- */
- public function test_with_draft_post() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
- $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
- $_POST['comment_post_ID'] = self::$draft_post->ID;
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( 'You cannot reply to a comment on a draft post.' );
- $this->_handleAjax( 'replyto-comment' );
- }
-
- /**
- * Tests reply to a post with a simulated database failure.
- *
- * Expects test to fail.
- *
- * @global $wpdb
- */
- public function test_blocked_comment() {
- global $wpdb;
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
- $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
- $_POST['comment_post_ID'] = self::$comment_post->ID;
-
- // Block comments from being saved, simulate a DB error.
- add_filter( 'query', array( $this, '_block_comments' ) );
-
- // Make the request.
- try {
- $wpdb->suppress_errors( true );
- $this->_handleAjax( 'replyto-comment' );
- $wpdb->suppress_errors( false );
- $this->fail();
- } catch ( WPAjaxDieStopException $e ) {
- $wpdb->suppress_errors( false );
- $this->assertStringContainsString( '1', $e->getMessage() );
- }
- }
-
- /**
- * Blocks comments from being saved.
- *
- * @param string $sql
- * @return string
- */
- public function _block_comments( $sql ) {
- global $wpdb;
- if ( false !== strpos( $sql, $wpdb->comments ) && 0 === stripos( trim( $sql ), 'INSERT INTO' ) ) {
- return '';
- }
- return $sql;
- }
-
- /**
- * Tests blocking a comment from being saved on 'pre_comment_approved'.
- *
- * @ticket 39730
- */
- public function test_pre_comments_approved() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
- $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
- $_POST['comment_post_ID'] = self::$comment_post->ID;
-
- // Simulate filter check error.
- add_filter( 'pre_comment_approved', array( $this, '_pre_comment_approved_filter' ), 10, 2 );
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( 'pre_comment_approved filter fails for new comment.' );
- $this->_handleAjax( 'replyto-comment' );
- }
-
- /**
- * Blocks comments from being saved on 'pre_comment_approved', by returning WP_Error.
- */
- public function _pre_comment_approved_filter( $approved, $commentdata ) {
- return new WP_Error( 'comment_wrong', 'pre_comment_approved filter fails for new comment.', 403 );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxResponsephp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/Response.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/Response.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/Response.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,107 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Testing Ajax response class
- *
- * @package WordPress
- * @subpackage UnitTests
- * @since 3.5.0
- * @group ajax
- *
- * @covers WP_Ajax_Response::send
- */
-class Tests_Ajax_Response extends WP_UnitTestCase {
-
- /**
- * Saved error reporting level
- *
- * @var int
- */
- protected $_error_level = 0;
-
- /**
- * Set up the test fixture.
- * Override wp_die(), pretend to be ajax, and suppres E_WARNINGs
- */
- public function set_up() {
- parent::set_up();
-
- add_filter( 'wp_die_ajax_handler', array( $this, 'getDieHandler' ), 1, 1 );
- add_filter( 'wp_doing_ajax', '__return_true' );
-
- // Suppress warnings from "Cannot modify header information - headers already sent by".
- $this->_error_level = error_reporting();
- error_reporting( $this->_error_level & ~E_WARNING );
- }
-
- /**
- * Tear down the test fixture.
- * Remove the wp_die() override, restore error reporting
- */
- public function tear_down() {
- remove_filter( 'wp_die_ajax_handler', array( $this, 'getDieHandler' ), 1, 1 );
- error_reporting( $this->_error_level );
- parent::tear_down();
- }
-
- /**
- * Return our callback handler
- *
- * @return callback
- */
- public function getDieHandler() {
- return array( $this, 'dieHandler' );
- }
-
- /**
- * Handler for wp_die()
- * Don't die, just continue on.
- *
- * @param string $message
- */
- public function dieHandler( $message ) {
- }
-
- /**
- * Test that charset in header matches blog_charset
- * Note: headers_list doesn't work properly in CLI mode, fall back on
- * xdebug_get_headers if it's available
- * Needs a separate process to get around the headers/output from the
- * bootstrapper
- *
- * @ticket 19448
- * @runInSeparateProcess
- * @preserveGlobalState disabled
- * @group xdebug
- * @requires function xdebug_get_headers
- */
- public function test_response_charset_in_header() {
-
- // Generate an Ajax response.
- ob_start();
- $ajax_response = new WP_Ajax_Response();
- $ajax_response->send();
-
- // Check the header.
- $headers = xdebug_get_headers();
- ob_end_clean();
-
- $this->assertContains( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), $headers );
- }
-
- /**
- * Test that charset in the xml tag matches blog_charset
- *
- * @ticket 19448
- */
- public function test_response_charset_in_xml() {
-
- // Generate an Ajax response.
- ob_start();
- $ajax_response = new WP_Ajax_Response();
- $ajax_response->send();
-
- // Check the XML tag.
- $contents = ob_get_clean();
- $this->assertMatchesRegularExpression( '/<\?xml\s+version=\'1.0\'\s+encoding=\'' . preg_quote( get_option( 'blog_charset' ) ) . '\'\s+standalone=\'yes\'\?>/', $contents );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxTagSearchphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/TagSearch.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/TagSearch.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/TagSearch.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,195 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Ajax tag search functionality.
- *
- * @package WordPress
- * @subpackage UnitTests
- * @since 3.4.0
- * @group ajax
- *
- * @covers ::wp_ajax_ajax_tag_search
- */
-class Tests_Ajax_TagSearch extends WP_Ajax_UnitTestCase {
-
- /**
- * List of terms to insert on setup
- *
- * @var array
- */
- private static $terms = array(
- 'chattels',
- 'depo',
- 'energumen',
- 'figuriste',
- 'habergeon',
- 'impropriation',
- );
-
- private static $term_ids = array();
-
- public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
- foreach ( self::$terms as $t ) {
- self::$term_ids[] = wp_insert_term( $t, 'post_tag' );
- }
- }
-
- /**
- * Test as an admin
- */
- public function test_post_tag() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_GET['tax'] = 'post_tag';
- $_GET['q'] = 'chat';
-
- // Make the request.
- try {
- $this->_handleAjax( 'ajax-tag-search' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Ensure we found the right match.
- $this->assertSame( $this->_last_response, 'chattels' );
- }
-
- /**
- * Test with no results
- */
- public function test_no_results() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_GET['tax'] = 'post_tag';
- $_GET['q'] = md5( uniqid() );
-
- // Make the request.
- // No output, so we get a stop exception.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '' );
- $this->_handleAjax( 'ajax-tag-search' );
- }
-
- /**
- * Test with commas
- */
- public function test_with_comma() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_GET['tax'] = 'post_tag';
- $_GET['q'] = 'some,nonsense, terms,chat'; // Only the last term in the list is searched.
-
- // Make the request.
- try {
- $this->_handleAjax( 'ajax-tag-search' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Ensure we found the right match.
- $this->assertSame( $this->_last_response, 'chattels' );
- }
-
- /**
- * Test as a logged out user
- */
- public function test_logged_out() {
-
- // Log out.
- wp_logout();
-
- // Set up a default request.
- $_GET['tax'] = 'post_tag';
- $_GET['q'] = 'chat';
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'ajax-tag-search' );
- }
-
- /**
- * Test with an invalid taxonomy type
- */
- public function test_invalid_tax() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_GET['tax'] = 'invalid-taxonomy';
- $_GET['q'] = 'chat';
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '0' );
- $this->_handleAjax( 'ajax-tag-search' );
- }
-
- /**
- * Test as an unprivileged user
- */
- public function test_unprivileged_user() {
-
- // Become a subscriber.
- $this->_setRole( 'subscriber' );
-
- // Set up a default request.
- $_GET['tax'] = 'post_tag';
- $_GET['q'] = 'chat';
-
- // Make the request.
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'ajax-tag-search' );
- }
-
- /**
- * Test the ajax_term_search_results filter
- *
- * @ticket 55606
- */
- public function test_ajax_term_search_results_filter() {
-
- // Become an administrator.
- $this->_setRole( 'administrator' );
-
- // Set up a default request.
- $_GET['tax'] = 'post_tag';
- $_GET['q'] = 'chat';
-
- // Add the ajax_term_search_results filter.
- add_filter(
- 'ajax_term_search_results',
- static function( $results, $tax, $s ) {
- return array( 'ajax_term_search_results was applied' );
- },
- 10,
- 3
- );
-
- // Make the request.
- try {
- $this->_handleAjax( 'ajax-tag-search', $_GET['tax'], $_GET['q'] );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Ensure we found the right match.
- $this->assertSame( 'ajax_term_search_results was applied', $this->_last_response );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxUpdatePluginphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/phpunit/tests/ajax/UpdatePlugin.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/UpdatePlugin.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/UpdatePlugin.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,173 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-/**
- * Admin Ajax functions to be tested.
- */
-require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
-
-/**
- * Testing Ajax handler for updating a plugin.
- *
- * @group ajax
- *
- * @covers ::wp_ajax_update_plugin
- */
-class Tests_Ajax_Update_Plugin extends WP_Ajax_UnitTestCase {
-
- public function test_missing_nonce() {
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_handleAjax( 'update-plugin' );
- }
-
- public function test_missing_plugin() {
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
- $_POST['slug'] = 'foo';
-
- // Make the request.
- try {
- $this->_handleAjax( 'update-plugin' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = array(
- 'success' => false,
- 'data' => array(
- 'slug' => '',
- 'errorCode' => 'no_plugin_specified',
- 'errorMessage' => 'No plugin specified.',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-
- public function test_missing_slug() {
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
- $_POST['plugin'] = 'foo/bar.php';
-
- // Make the request.
- try {
- $this->_handleAjax( 'update-plugin' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = array(
- 'success' => false,
- 'data' => array(
- 'slug' => '',
- 'errorCode' => 'no_plugin_specified',
- 'errorMessage' => 'No plugin specified.',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-
- public function test_missing_capability() {
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
- $_POST['plugin'] = 'foo/bar.php';
- $_POST['slug'] = 'foo';
-
- // Make the request.
- try {
- $this->_handleAjax( 'update-plugin' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = array(
- 'success' => false,
- 'data' => array(
- 'update' => 'plugin',
- 'slug' => 'foo',
- 'oldVersion' => '',
- 'newVersion' => '',
- 'errorMessage' => 'Sorry, you are not allowed to update plugins for this site.',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-
- public function test_invalid_file() {
- $this->_setRole( 'administrator' );
-
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
- $_POST['plugin'] = '../foo/bar.php';
- $_POST['slug'] = 'foo';
-
- // Make the request.
- try {
- $this->_handleAjax( 'update-plugin' );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = array(
- 'success' => false,
- 'data' => array(
- 'update' => 'plugin',
- 'slug' => 'foo',
- 'oldVersion' => '',
- 'newVersion' => '',
- 'errorMessage' => 'Sorry, you are not allowed to update plugins for this site.',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-
- /**
- * @group ms-excluded
- */
- public function test_update_plugin() {
- $this->_setRole( 'administrator' );
-
- $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
- $_POST['plugin'] = 'hello.php';
- $_POST['slug'] = 'hello-dolly';
-
- // Make the request.
- try {
- // Prevent wp_update_plugins() from running.
- wp_installing( true );
- $this->_handleAjax( 'update-plugin' );
- wp_installing( false );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
-
- // Get the response.
- $response = json_decode( $this->_last_response, true );
-
- $expected = array(
- 'success' => false,
- 'data' => array(
- 'update' => 'plugin',
- 'slug' => 'hello-dolly',
- 'oldVersion' => 'Version 1.7.2',
- 'newVersion' => '',
- 'plugin' => 'hello.php',
- 'pluginName' => 'Hello Dolly',
- 'debug' => array( 'The plugin is at the latest version.' ),
- 'errorMessage' => 'The plugin is at the latest version.',
- ),
- );
-
- $this->assertSameSets( $expected, $response );
- }
-}
</del></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxAddMetaphpfromrev54721trunktestsphpunittestsajaxAddMetaphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxAddMeta.php (from rev 54721, trunk/tests/phpunit/tests/ajax/AddMeta.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxAddMeta.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxAddMeta.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,78 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Add Meta AJAX functionality.
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_add_meta
+ */
+class Tests_Ajax_wpAjaxAddMeta extends WP_Ajax_UnitTestCase {
+
+ /**
+ * @ticket 43559
+ *
+ * @covers ::add_post_meta
+ */
+ public function test_wp_ajax_add_meta_allows_empty_values_on_adding() {
+ $post = self::factory()->post->create();
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ $_POST = array(
+ 'post_id' => $post,
+ 'metakeyinput' => 'testkey',
+ 'metavalue' => '',
+ '_ajax_nonce-add-meta' => wp_create_nonce( 'add-meta' ),
+ );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'add-meta' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ $this->assertSame( '', get_post_meta( $post, 'testkey', true ) );
+ }
+
+ /**
+ * @ticket 43559
+ *
+ * @covers ::update_metadata_by_mid
+ */
+ public function test_wp_ajax_add_meta_allows_empty_values_on_updating() {
+ $post = self::factory()->post->create();
+
+ $meta_id = add_post_meta( $post, 'testkey', 'hello' );
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ $_POST = array(
+ '_ajax_nonce-add-meta' => wp_create_nonce( 'add-meta' ),
+ 'post_id' => $post,
+ 'meta' => array(
+ $meta_id => array(
+ 'key' => 'testkey',
+ 'value' => '',
+ ),
+ ),
+ );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'add-meta' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ $this->assertSame( '', get_post_meta( $post, 'testkey', true ) );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxAddTagphpfromrev54721trunktestsphpunittestsajaxAddTagphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxAddTag.php (from rev 54721, trunk/tests/phpunit/tests/ajax/AddTag.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxAddTag.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxAddTag.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,154 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Admin ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Class for testing ajax add tag functionality.
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_add_tag
+ */
+class Tests_Ajax_wpAjaxAddTag extends WP_Ajax_UnitTestCase {
+
+ /**
+ * @dataProvider data_add_tag
+ *
+ * @ticket 42937
+ *
+ * @covers ::wp_insert_term
+ *
+ * @param array $post_data Data to populate $_POST.
+ * @param string $expected Expected response.
+ * @param array|string|callable $callback Optional. Callback to register to 'term_updated_messages'
+ * filter. Default empty string (no callback).
+ */
+ public function test_add_tag( array $post_data, $expected, $callback = '' ) {
+ $this->_setRole( 'administrator' );
+
+ $_POST = $post_data;
+ $_POST['_wpnonce_add-tag'] = wp_create_nonce( 'add-tag' );
+
+ if ( ! empty( $callback ) ) {
+ add_filter( 'term_updated_messages', $callback );
+ }
+
+ try {
+ $this->_handleAjax( 'add-tag' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // The response message is in the `data` property in WP 5.9.
+ $this->assertSame( $expected, (string) $this->get_xml_response_taxonomy()->response_data );
+ // The response message is in the `supplemental->notice` property in WP 6.0+.
+ $this->assertSame( $expected, (string) $this->get_xml_response_taxonomy()->supplemental->notice );
+ }
+
+ /**
+ * Data provider.
+ *
+ * @return array
+ */
+ public function data_add_tag() {
+ return array(
+ 'add a category' => array(
+ 'post_data' => array(
+ 'taxonomy' => 'category',
+ 'post_type' => 'post',
+ 'screen' => 'edit-category',
+ 'action' => 'add-tag',
+ 'tag-name' => 'blues',
+ ),
+ 'expected' => 'Category added.',
+ ),
+ 'add a category with message filtering' => array(
+ 'post_data' => array(
+ 'taxonomy' => 'category',
+ 'post_type' => 'post',
+ 'screen' => 'edit-category',
+ 'action' => 'add-tag',
+ 'tag-name' => 'techno',
+ ),
+ 'expected' => 'A new category added.',
+ 'callback' => static function( array $messages ) {
+ $messages['category'][1] = 'A new category added.';
+ return $messages;
+ },
+ ),
+ 'add a post_tag' => array(
+ 'post_data' => array(
+ 'taxonomy' => 'post_tag',
+ 'post_type' => 'post',
+ 'screen' => 'edit-post_tag',
+ 'action' => 'add-tag',
+ 'tag-name' => 'Louis Armstrong',
+ ),
+ 'expected' => 'Tag added.',
+ ),
+ );
+ }
+
+ /**
+ * @ticket 42937
+ */
+ public function test_adding_category_without_capability_should_error() {
+ $this->_setRole( 'subscriber' );
+
+ $_POST['taxonomy'] = 'category';
+ $_POST['post_type'] = 'post';
+ $_POST['screen'] = 'edit-category';
+ $_POST['action'] = 'add-tag';
+ $_POST['tag - name'] = 'disco';
+ $_POST['_wpnonce_add-tag'] = wp_create_nonce( 'add-tag' );
+
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'add-tag' );
+ }
+
+ /**
+ * @ticket 42937
+ *
+ * @covers ::wp_insert_term
+ */
+ public function test_adding_existing_category_should_error() {
+ $this->_setRole( 'administrator' );
+
+ wp_insert_term( 'testcat', 'category' );
+
+ $_POST = array(
+ 'taxonomy' => 'category',
+ 'post_type' => 'post',
+ 'screen' => 'edit-category',
+ 'action' => 'add-tag',
+ 'tag-name' => 'testcat',
+ '_wpnonce_add-tag' => wp_create_nonce( 'add-tag' ),
+ );
+
+ try {
+ $this->_handleAjax( 'add-tag' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ $expected = 'A term with the name provided already exists with this parent.';
+ $this->assertSame( $expected, (string) $this->get_xml_response_taxonomy()->wp_error );
+ }
+
+ /**
+ * Helper method to get the taxonomy's response or error.
+ *
+ * @since 5.9.0
+ *
+ * @return SimpleXMLElement Response or error object.
+ */
+ private function get_xml_response_taxonomy() {
+ $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
+
+ return $xml->response->taxonomy;
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxAjaxTagSearchphpfromrev54721trunktestsphpunittestsajaxTagSearchphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxAjaxTagSearch.php (from rev 54721, trunk/tests/phpunit/tests/ajax/TagSearch.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxAjaxTagSearch.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxAjaxTagSearch.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,196 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Ajax tag search functionality.
+ *
+ * @package WordPress
+ * @subpackage UnitTests
+ * @since 3.4.0
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_ajax_tag_search
+ */
+class Tests_Ajax_wpAjaxAjaxTagSearch extends WP_Ajax_UnitTestCase {
+
+ /**
+ * List of terms to insert on setup
+ *
+ * @var array
+ */
+ private static $terms = array(
+ 'chattels',
+ 'depo',
+ 'energumen',
+ 'figuriste',
+ 'habergeon',
+ 'impropriation',
+ );
+
+ private static $term_ids = array();
+
+ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
+ foreach ( self::$terms as $t ) {
+ self::$term_ids[] = wp_insert_term( $t, 'post_tag' );
+ }
+ }
+
+ /**
+ * Test as an admin
+ */
+ public function test_post_tag() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_GET['tax'] = 'post_tag';
+ $_GET['q'] = 'chat';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'ajax-tag-search' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Ensure we found the right match.
+ $this->assertSame( $this->_last_response, 'chattels' );
+ }
+
+ /**
+ * Test with no results
+ */
+ public function test_no_results() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_GET['tax'] = 'post_tag';
+ $_GET['q'] = md5( uniqid() );
+
+ // Make the request.
+ // No output, so we get a stop exception.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '' );
+ $this->_handleAjax( 'ajax-tag-search' );
+ }
+
+ /**
+ * Test with commas
+ */
+ public function test_with_comma() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_GET['tax'] = 'post_tag';
+ $_GET['q'] = 'some,nonsense, terms,chat'; // Only the last term in the list is searched.
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'ajax-tag-search' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Ensure we found the right match.
+ $this->assertSame( $this->_last_response, 'chattels' );
+ }
+
+ /**
+ * Test as a logged out user
+ */
+ public function test_logged_out() {
+
+ // Log out.
+ wp_logout();
+
+ // Set up a default request.
+ $_GET['tax'] = 'post_tag';
+ $_GET['q'] = 'chat';
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'ajax-tag-search' );
+ }
+
+ /**
+ * Test with an invalid taxonomy type
+ */
+ public function test_invalid_tax() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_GET['tax'] = 'invalid-taxonomy';
+ $_GET['q'] = 'chat';
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '0' );
+ $this->_handleAjax( 'ajax-tag-search' );
+ }
+
+ /**
+ * Test as an unprivileged user
+ */
+ public function test_unprivileged_user() {
+
+ // Become a subscriber.
+ $this->_setRole( 'subscriber' );
+
+ // Set up a default request.
+ $_GET['tax'] = 'post_tag';
+ $_GET['q'] = 'chat';
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'ajax-tag-search' );
+ }
+
+ /**
+ * Test the ajax_term_search_results filter
+ *
+ * @ticket 55606
+ */
+ public function test_ajax_term_search_results_filter() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_GET['tax'] = 'post_tag';
+ $_GET['q'] = 'chat';
+
+ // Add the ajax_term_search_results filter.
+ add_filter(
+ 'ajax_term_search_results',
+ static function( $results, $tax, $s ) {
+ return array( 'ajax_term_search_results was applied' );
+ },
+ 10,
+ 3
+ );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'ajax-tag-search', $_GET['tax'], $_GET['q'] );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Ensure we found the right match.
+ $this->assertSame( 'ajax_term_search_results was applied', $this->_last_response );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxCropImagephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/ajax/wpAjaxCropImage.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxCropImage.php 2022-10-29 17:10:29 UTC (rev 54721)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxCropImage.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11,6 +11,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Class for testing ajax crop image functionality.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @group ajax
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers ::wp_ajax_crop_image
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> class Tests_Ajax_WpAjaxCropImage extends WP_Ajax_UnitTestCase {
</span></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxDeleteCommentphpfromrev54721trunktestsphpunittestsajaxDeleteCommentphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxDeleteComment.php (from rev 54721, trunk/tests/phpunit/tests/ajax/DeleteComment.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxDeleteComment.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxDeleteComment.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,352 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Ajax comment functionality.
+ *
+ * @package WordPress
+ * @subpackage UnitTests
+ * @since 3.4.0
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_delete_comment
+ */
+class Tests_Ajax_wpAjaxDeleteComment extends WP_Ajax_UnitTestCase {
+
+ /**
+ * List of comments.
+ *
+ * @var array
+ */
+ protected static $comments = array();
+
+ /**
+ * ID of a post.
+ *
+ * @var int
+ */
+ protected static $post_id;
+
+ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
+ self::$post_id = $factory->post->create();
+
+ $comment_ids = $factory->comment->create_post_comments( self::$post_id, 8 );
+ self::$comments = array_map( 'get_comment', $comment_ids );
+ }
+
+ /**
+ * Clears the POST actions in between requests.
+ */
+ protected function _clear_post_action() {
+ unset( $_POST['trash'] );
+ unset( $_POST['untrash'] );
+ unset( $_POST['spam'] );
+ unset( $_POST['unspam'] );
+ unset( $_POST['delete'] );
+ $this->_last_response = '';
+ }
+
+ /*
+ * Test prototype
+ */
+
+ /**
+ * Tests as a privileged user (administrator).
+ *
+ * Expects test to pass.
+ *
+ * @covers ::_wp_ajax_delete_comment_response
+ *
+ * @param WP_Comment $comment Comment object.
+ * @param string $action Action: 'trash', 'untrash', etc.
+ */
+ public function _test_as_admin( $comment, $action ) {
+
+ // Reset request.
+ $this->_clear_post_action();
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_POST['id'] = $comment->comment_ID;
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'delete-comment_' . $comment->comment_ID );
+ $_POST[ $action ] = 1;
+ $_POST['_total'] = count( self::$comments );
+ $_POST['_per_page'] = 100;
+ $_POST['_page'] = 1;
+ $_POST['_url'] = admin_url( 'edit-comments.php' );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'delete-comment' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
+
+ // Ensure everything is correct.
+ $this->assertSame( $comment->comment_ID, (string) $xml->response[0]->comment['id'] );
+ $this->assertSame( 'delete-comment_' . $comment->comment_ID, (string) $xml->response['action'] );
+ $this->assertGreaterThanOrEqual( time() - 10, (int) $xml->response[0]->comment[0]->supplemental[0]->time[0] );
+ $this->assertLessThanOrEqual( time(), (int) $xml->response[0]->comment[0]->supplemental[0]->time[0] );
+
+ // 'trash', 'spam', 'delete' should make the total go down.
+ if ( in_array( $action, array( 'trash', 'spam', 'delete' ), true ) ) {
+ $total = $_POST['_total'] - 1;
+
+ // 'unspam', 'untrash' should make the total go up.
+ } elseif ( in_array( $action, array( 'untrash', 'unspam' ), true ) ) {
+ $total = $_POST['_total'] + 1;
+ }
+
+ // The total is calculated based on a page break -OR- a random number. Let's look for both possible outcomes.
+ $comment_count = wp_count_comments( 0 );
+ $recalc_total = $comment_count->total_comments;
+
+ // Check for either possible total.
+ $message = sprintf( 'returned value: %1$d $total: %2$d $recalc_total: %3$d', (int) $xml->response[0]->comment[0]->supplemental[0]->total[0], $total, $recalc_total );
+ $this->assertContains( (int) $xml->response[0]->comment[0]->supplemental[0]->total[0], array( $total, $recalc_total ), $message );
+ }
+
+ /**
+ * Tests as a non-privileged user (subscriber).
+ *
+ * Expects test to fail.
+ *
+ * @param WP_Comment $comment Comment object.
+ * @param string $action Action: 'trash', 'untrash', etc.
+ */
+ public function _test_as_subscriber( $comment, $action ) {
+
+ // Reset request.
+ $this->_clear_post_action();
+
+ // Become a subscriber.
+ $this->_setRole( 'subscriber' );
+
+ // Set up the $_POST request.
+ $_POST['id'] = $comment->comment_ID;
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'delete-comment_' . $comment->comment_ID );
+ $_POST[ $action ] = 1;
+ $_POST['_total'] = count( self::$comments );
+ $_POST['_per_page'] = 100;
+ $_POST['_page'] = 1;
+ $_POST['_url'] = admin_url( 'edit-comments.php' );
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'delete-comment' );
+ }
+
+
+ /**
+ * Tests with a bad nonce.
+ *
+ * Expects test to fail.
+ *
+ * @param WP_Comment $comment Comment object.
+ * @param string $action Action: 'trash', 'untrash', etc.
+ */
+ public function _test_with_bad_nonce( $comment, $action ) {
+
+ // Reset request.
+ $this->_clear_post_action();
+
+ // Become a subscriber.
+ $this->_setRole( 'administrator' );
+
+ // Set up the $_POST request.
+ $_POST['id'] = $comment->comment_ID;
+ $_POST['_ajax_nonce'] = wp_create_nonce( uniqid() );
+ $_POST[ $action ] = 1;
+ $_POST['_total'] = count( self::$comments );
+ $_POST['_per_page'] = 100;
+ $_POST['_page'] = 1;
+ $_POST['_url'] = admin_url( 'edit-comments.php' );
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'delete-comment' );
+ }
+
+ /**
+ * Tests with a bad ID.
+ *
+ * Expects test to fail.
+ *
+ * @param WP_Comment $comment Comment object.
+ * @param string $action Action: 'trash', 'untrash', etc.
+ */
+ public function _test_with_bad_id( $comment, $action ) {
+
+ // Reset request.
+ $this->_clear_post_action();
+
+ // Become a subscriber.
+ $this->_setRole( 'administrator' );
+
+ // Set up the $_POST request.
+ $_POST['id'] = 12346789;
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'delete-comment_12346789' );
+ $_POST[ $action ] = 1;
+ $_POST['_total'] = count( self::$comments );
+ $_POST['_per_page'] = 100;
+ $_POST['_page'] = 1;
+ $_POST['_url'] = admin_url( 'edit-comments.php' );
+
+ // Make the request, look for a timestamp in the exception.
+ try {
+ $this->_handleAjax( 'delete-comment' );
+ $this->fail( 'Expected exception: WPAjaxDieStopException' );
+ } catch ( WPAjaxDieStopException $e ) {
+ $this->assertSame( 10, strlen( $e->getMessage() ) );
+ $this->assertIsNumeric( $e->getMessage() );
+ } catch ( Exception $e ) {
+ $this->fail( 'Unexpected exception type: ' . get_class( $e ) );
+ }
+ }
+
+ /**
+ * Tests doubling the action (e.g. trash a trashed comment).
+ *
+ * Expects test to fail.
+ *
+ * @param WP_Comment $comment Comment object.
+ * @param string $action Action: 'trash', 'untrash', etc.
+ */
+ public function _test_double_action( $comment, $action ) {
+
+ // Reset request.
+ $this->_clear_post_action();
+
+ // Become a subscriber.
+ $this->_setRole( 'administrator' );
+
+ // Set up the $_POST request.
+ $_POST['id'] = $comment->comment_ID;
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'delete-comment_' . $comment->comment_ID );
+ $_POST[ $action ] = 1;
+ $_POST['_total'] = count( self::$comments );
+ $_POST['_per_page'] = 100;
+ $_POST['_page'] = 1;
+ $_POST['_url'] = admin_url( 'edit-comments.php' );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'delete-comment' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+ $this->_last_response = '';
+
+ // Force delete the comment.
+ if ( 'delete' === $action ) {
+ wp_delete_comment( $comment->comment_ID, true );
+ }
+
+ // Make the request again, look for a timestamp in the exception.
+ try {
+ $this->_handleAjax( 'delete-comment' );
+ $this->fail( 'Expected exception: WPAjaxDieStopException' );
+ } catch ( WPAjaxDieStopException $e ) {
+ $this->assertSame( 10, strlen( $e->getMessage() ) );
+ $this->assertIsNumeric( $e->getMessage() );
+ } catch ( Exception $e ) {
+ $this->fail( 'Unexpected exception type: ' . get_class( $e ) );
+ }
+ }
+
+ /**
+ * Deletes a comment as an administrator (expects success).
+ *
+ * @covers ::_wp_ajax_delete_comment_response
+ */
+ public function test_ajax_comment_trash_actions_as_administrator() {
+ // Test trash/untrash.
+ $this->_test_as_admin( self::$comments[0], 'trash' );
+ $this->_test_as_admin( self::$comments[0], 'untrash' );
+
+ // Test spam/unspam.
+ $this->_test_as_admin( self::$comments[1], 'spam' );
+ $this->_test_as_admin( self::$comments[1], 'unspam' );
+
+ // Test delete.
+ $this->_test_as_admin( self::$comments[2], 'delete' );
+ }
+
+ /**
+ * Deletes a comment as a subscriber (expects permission denied).
+ */
+ public function test_ajax_comment_trash_actions_as_subscriber() {
+ // Test trash/untrash.
+ $this->_test_as_subscriber( self::$comments[0], 'trash' );
+ $this->_test_as_subscriber( self::$comments[0], 'untrash' );
+
+ // Test spam/unspam.
+ $this->_test_as_subscriber( self::$comments[1], 'spam' );
+ $this->_test_as_subscriber( self::$comments[1], 'unspam' );
+
+ // Test delete.
+ $this->_test_as_subscriber( self::$comments[2], 'delete' );
+ }
+
+ /**
+ * Deletes a comment with no ID.
+ *
+ * @covers ::_wp_ajax_delete_comment_response
+ */
+ public function test_ajax_trash_comment_no_id() {
+ // Test trash/untrash.
+ $this->_test_as_admin( self::$comments[0], 'trash' );
+ $this->_test_as_admin( self::$comments[0], 'untrash' );
+
+ // Test spam/unspam.
+ $this->_test_as_admin( self::$comments[1], 'spam' );
+ $this->_test_as_admin( self::$comments[1], 'unspam' );
+
+ // Test delete.
+ $this->_test_as_admin( self::$comments[2], 'delete' );
+ }
+
+ /**
+ * Deletes a comment with a bad nonce.
+ */
+ public function test_ajax_trash_comment_bad_nonce() {
+ // Test trash/untrash.
+ $this->_test_with_bad_nonce( self::$comments[0], 'trash' );
+ $this->_test_with_bad_nonce( self::$comments[0], 'untrash' );
+
+ // Test spam/unspam.
+ $this->_test_with_bad_nonce( self::$comments[1], 'spam' );
+ $this->_test_with_bad_nonce( self::$comments[1], 'unspam' );
+
+ // Test delete.
+ $this->_test_with_bad_nonce( self::$comments[2], 'delete' );
+ }
+
+ /**
+ * Tests trashing an already trashed comment, etc.
+ */
+ public function test_ajax_trash_double_action() {
+ // Test trash/untrash.
+ $this->_test_double_action( self::$comments[0], 'trash' );
+ $this->_test_double_action( self::$comments[0], 'untrash' );
+
+ // Test spam/unspam.
+ $this->_test_double_action( self::$comments[1], 'spam' );
+ $this->_test_double_action( self::$comments[1], 'unspam' );
+
+ // Test delete.
+ $this->_test_double_action( self::$comments[2], 'delete' );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxDeletePluginphpfromrev54721trunktestsphpunittestsajaxDeletePluginphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxDeletePlugin.php (from rev 54721, trunk/tests/phpunit/tests/ajax/DeletePlugin.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxDeletePlugin.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxDeletePlugin.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,164 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Ajax handler for deleting a plugin.
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_delete_plugin
+ */
+class Tests_Ajax_wpAjaxDeletePlugin extends WP_Ajax_UnitTestCase {
+
+ public function test_missing_nonce() {
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'delete-plugin' );
+ }
+
+ public function test_missing_plugin() {
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+ $_POST['slug'] = 'foo';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'delete-plugin' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = array(
+ 'success' => false,
+ 'data' => array(
+ 'slug' => '',
+ 'errorCode' => 'no_plugin_specified',
+ 'errorMessage' => 'No plugin specified.',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+
+ public function test_missing_slug() {
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+ $_POST['plugin'] = 'foo/bar.php';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'delete-plugin' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = array(
+ 'success' => false,
+ 'data' => array(
+ 'slug' => '',
+ 'errorCode' => 'no_plugin_specified',
+ 'errorMessage' => 'No plugin specified.',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+
+ public function test_missing_capability() {
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+ $_POST['plugin'] = 'foo/bar.php';
+ $_POST['slug'] = 'foo';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'delete-plugin' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = array(
+ 'success' => false,
+ 'data' => array(
+ 'delete' => 'plugin',
+ 'slug' => 'foo',
+ 'errorMessage' => 'Sorry, you are not allowed to delete plugins for this site.',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+
+ public function test_invalid_file() {
+ $this->_setRole( 'administrator' );
+
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+ $_POST['plugin'] = '../foo/bar.php';
+ $_POST['slug'] = 'foo';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'delete-plugin' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = array(
+ 'success' => false,
+ 'data' => array(
+ 'delete' => 'plugin',
+ 'slug' => 'foo',
+ 'errorMessage' => 'Sorry, you are not allowed to delete plugins for this site.',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+
+ /**
+ * @group ms-excluded
+ *
+ * @covers ::delete_plugins
+ */
+ public function test_delete_plugin() {
+ $this->_setRole( 'administrator' );
+
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+ $_POST['plugin'] = 'foo.php';
+ $_POST['slug'] = 'foo';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'delete-plugin' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = array(
+ 'success' => true,
+ 'data' => array(
+ 'delete' => 'plugin',
+ 'slug' => 'foo',
+ 'plugin' => 'foo.php',
+ 'pluginName' => '',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxDimCommentphpfromrev54721trunktestsphpunittestsajaxDimCommentphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxDimComment.php (from rev 54721, trunk/tests/phpunit/tests/ajax/DimComment.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxDimComment.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxDimComment.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,242 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Ajax comment functionality
+ *
+ * @package WordPress
+ * @subpackage UnitTests
+ * @since 3.4.0
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_dim_comment
+ */
+class Tests_Ajax_wpAjaxDimComment extends WP_Ajax_UnitTestCase {
+
+ /**
+ * List of comments.
+ *
+ * @var array
+ */
+ protected $_comments = array();
+
+ /**
+ * Sets up the test fixture.
+ */
+ public function set_up() {
+ parent::set_up();
+ $post_id = self::factory()->post->create();
+ $this->_comments = self::factory()->comment->create_post_comments( $post_id, 15 );
+ $this->_comments = array_map( 'get_comment', $this->_comments );
+ }
+
+ /**
+ * Clears the POST actions in between requests.
+ */
+ protected function _clear_post_action() {
+ unset( $_POST['id'] );
+ unset( $_POST['new'] );
+ $this->_last_response = '';
+ }
+
+ /*
+ * Test prototype
+ */
+
+ /**
+ * Tests as a privileged user (administrator).
+ *
+ * Expects test to pass.
+ *
+ * @param WP_Comment $comment Comment object.
+ */
+ public function _test_as_admin( $comment ) {
+
+ // Reset request.
+ $this->_clear_post_action();
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_POST['id'] = $comment->comment_ID;
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'approve-comment_' . $comment->comment_ID );
+ $_POST['_total'] = count( $this->_comments );
+ $_POST['_per_page'] = 100;
+ $_POST['_page'] = 1;
+ $_POST['_url'] = admin_url( 'edit-comments.php' );
+
+ // Save the comment status.
+ $prev_status = wp_get_comment_status( $comment->comment_ID );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'dim-comment' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
+
+ // Ensure everything is correct.
+ $this->assertSame( $comment->comment_ID, (string) $xml->response[0]->comment['id'] );
+ $this->assertSame( 'dim-comment_' . $comment->comment_ID, (string) $xml->response['action'] );
+ $this->assertGreaterThanOrEqual( time() - 10, (int) $xml->response[0]->comment[0]->supplemental[0]->time[0] );
+ $this->assertLessThanOrEqual( time(), (int) $xml->response[0]->comment[0]->supplemental[0]->time[0] );
+
+ // Check the status.
+ $current = wp_get_comment_status( $comment->comment_ID );
+ if ( in_array( $prev_status, array( 'unapproved', 'spam' ), true ) ) {
+ $this->assertSame( 'approved', $current );
+ } else {
+ $this->assertSame( 'unapproved', $current );
+ }
+
+ // The total is calculated based on a page break -OR- a random number. Let's look for both possible outcomes.
+ $comment_count = wp_count_comments( 0 );
+ $recalc_total = $comment_count->total_comments;
+
+ // Delta is not specified, it will always be 1 lower than the request.
+ $total = $_POST['_total'] - 1;
+
+ // Check for either possible total.
+ $this->assertContains( (int) $xml->response[0]->comment[0]->supplemental[0]->total[0], array( $total, $recalc_total ) );
+ }
+
+ /**
+ * Tests as a non-privileged user (subscriber).
+ *
+ * Expects test to fail.
+ *
+ * @param WP_Comment $comment Comment object.
+ */
+ public function _test_as_subscriber( $comment ) {
+
+ // Reset request.
+ $this->_clear_post_action();
+
+ // Become a subscriber.
+ $this->_setRole( 'subscriber' );
+
+ // Set up the $_POST request.
+ $_POST['id'] = $comment->comment_ID;
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'approve-comment_' . $comment->comment_ID );
+ $_POST['_total'] = count( $this->_comments );
+ $_POST['_per_page'] = 100;
+ $_POST['_page'] = 1;
+ $_POST['_url'] = admin_url( 'edit-comments.php' );
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'dim-comment' );
+ }
+
+ /**
+ * Tests with a bad nonce.
+ *
+ * Expects test to fail.
+ *
+ * @param WP_Comment $comment Comment object.
+ */
+ public function _test_with_bad_nonce( $comment ) {
+
+ // Reset request.
+ $this->_clear_post_action();
+
+ // Become a subscriber.
+ $this->_setRole( 'administrator' );
+
+ // Set up the $_POST request.
+ $_POST['id'] = $comment->comment_ID;
+ $_POST['_ajax_nonce'] = wp_create_nonce( uniqid() );
+ $_POST['_total'] = count( $this->_comments );
+ $_POST['_per_page'] = 100;
+ $_POST['_page'] = 1;
+ $_POST['_url'] = admin_url( 'edit-comments.php' );
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'dim-comment' );
+ }
+
+ /**
+ * Tests with a bad ID.
+ *
+ * Expects test to fail.
+ */
+ public function test_with_bad_id() {
+
+ // Reset request.
+ $this->_clear_post_action();
+
+ // Become a subscriber.
+ $this->_setRole( 'administrator' );
+
+ // Set up the $_POST request.
+ $_POST['id'] = 12346789;
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'dim-comment_12346789' );
+ $_POST['_total'] = count( $this->_comments );
+ $_POST['_per_page'] = 100;
+ $_POST['_page'] = 1;
+ $_POST['_url'] = admin_url( 'edit-comments.php' );
+
+ // Make the request, look for a timestamp in the exception.
+ try {
+ $this->_handleAjax( 'dim-comment' );
+ $this->fail( 'Expected exception: WPAjaxDieContinueException' );
+ } catch ( WPAjaxDieContinueException $e ) {
+
+ // Get the response.
+ $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
+
+ // Ensure everything is correct.
+ $this->assertSame( '0', (string) $xml->response[0]->comment['id'] );
+ $this->assertSame( 'dim-comment_0', (string) $xml->response['action'] );
+ $this->assertStringContainsString( 'Comment ' . $_POST['id'] . ' does not exist', $this->_last_response );
+
+ } catch ( Exception $e ) {
+ $this->fail( 'Unexpected exception type: ' . get_class( $e ) );
+ }
+ }
+
+ /**
+ * Dims a comment as an administrator (expects success).
+ */
+ public function test_ajax_comment_dim_actions_as_administrator() {
+ $comment = array_pop( $this->_comments );
+ $this->_test_as_admin( $comment );
+ $this->_test_as_admin( $comment );
+ }
+
+ /**
+ * Dims a comment as a subscriber (expects permission denied).
+ */
+ public function test_ajax_comment_dim_actions_as_subscriber() {
+ $comment = array_pop( $this->_comments );
+ $this->_test_as_subscriber( $comment );
+ }
+
+ /**
+ * Dims a comment with no ID.
+ */
+ public function test_ajax_dim_comment_no_id() {
+ $comment = array_pop( $this->_comments );
+ $this->_test_as_admin( $comment );
+ }
+
+ /**
+ * Dims a comment with a bad nonce.
+ */
+ public function test_ajax_dim_comment_bad_nonce() {
+ $comment = array_pop( $this->_comments );
+ $this->_test_with_bad_nonce( $comment );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxEditCommentphpfromrev54721trunktestsphpunittestsajaxEditCommentphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxEditComment.php (from rev 54721, trunk/tests/phpunit/tests/ajax/EditComment.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxEditComment.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxEditComment.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,245 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Ajax comment functionality.
+ *
+ * @package WordPress
+ * @subpackage UnitTests
+ * @since 3.4.0
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_edit_comment
+ */
+class Tests_Ajax_wpAjaxEditComment extends WP_Ajax_UnitTestCase {
+
+ /**
+ * A post with at least one comment.
+ *
+ * @var mixed
+ */
+ protected $_comment_post = null;
+
+ /**
+ * Sets up the test fixture.
+ */
+ public function set_up() {
+ parent::set_up();
+ $post_id = self::factory()->post->create();
+ self::factory()->comment->create_post_comments( $post_id, 5 );
+ $this->_comment_post = get_post( $post_id );
+ }
+
+ /**
+ * Gets comments as a privileged user (administrator).
+ *
+ * Expects test to pass.
+ */
+ public function test_as_admin() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Get a comment.
+ $comments = get_comments(
+ array(
+ 'post_id' => $this->_comment_post->ID,
+ )
+ );
+ $comment = array_pop( $comments );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
+ $_POST['comment_ID'] = $comment->comment_ID;
+ $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'edit-comment' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
+
+ // Check the meta data.
+ $this->assertSame( '-1', (string) $xml->response[0]->edit_comment['position'] );
+ $this->assertSame( $comment->comment_ID, (string) $xml->response[0]->edit_comment['id'] );
+ $this->assertSame( 'edit-comment_' . $comment->comment_ID, (string) $xml->response['action'] );
+
+ // Check the payload.
+ $this->assertNotEmpty( (string) $xml->response[0]->edit_comment[0]->response_data );
+
+ // And supplemental is empty.
+ $this->assertEmpty( (string) $xml->response[0]->edit_comment[0]->supplemental );
+ }
+
+ /**
+ * @ticket 33154
+ */
+ public function test_editor_can_edit_orphan_comments() {
+ global $wpdb;
+
+ // Become an editor.
+ $this->_setRole( 'editor' );
+
+ // Get a comment.
+ $comments = get_comments(
+ array(
+ 'post_id' => $this->_comment_post->ID,
+ )
+ );
+ $comment = array_pop( $comments );
+
+ // Manually update the comment_post_ID, because wp_update_comment() will prevent it..
+ $wpdb->update( $wpdb->comments, array( 'comment_post_ID' => 0 ), array( 'comment_ID' => $comment->comment_ID ) );
+ clean_comment_cache( $comment->comment_ID );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
+ $_POST['comment_ID'] = $comment->comment_ID;
+ $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'edit-comment' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
+
+ // Check the meta data.
+ $this->assertSame( '-1', (string) $xml->response[0]->edit_comment['position'] );
+ $this->assertSame( $comment->comment_ID, (string) $xml->response[0]->edit_comment['id'] );
+ $this->assertSame( 'edit-comment_' . $comment->comment_ID, (string) $xml->response['action'] );
+
+ // Check the payload.
+ $this->assertNotEmpty( (string) $xml->response[0]->edit_comment[0]->response_data );
+
+ // And supplemental is empty.
+ $this->assertEmpty( (string) $xml->response[0]->edit_comment[0]->supplemental );
+ }
+
+ /**
+ * Gets comments as a non-privileged user (subscriber).
+ *
+ * Expects test to fail.
+ */
+ public function test_as_subscriber() {
+
+ // Become a subscriber.
+ $this->_setRole( 'subscriber' );
+
+ // Get a comment.
+ $comments = get_comments(
+ array(
+ 'post_id' => $this->_comment_post->ID,
+ )
+ );
+ $comment = array_pop( $comments );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
+ $_POST['comment_ID'] = $comment->comment_ID;
+ $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'edit-comment' );
+ }
+
+ /**
+ * Gets comments with a bad nonce.
+ *
+ * Expects test to fail.
+ */
+ public function test_bad_nonce() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Get a comment.
+ $comments = get_comments(
+ array(
+ 'post_id' => $this->_comment_post->ID,
+ )
+ );
+ $comment = array_pop( $comments );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( uniqid() );
+ $_POST['comment_ID'] = $comment->comment_ID;
+ $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'get-comments' );
+ }
+
+ /**
+ * Gets comments for an invalid post.
+ *
+ * This should return valid XML.
+ */
+ public function test_invalid_comment() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
+ $_POST['comment_ID'] = 123456789;
+ $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'edit-comment' );
+ }
+
+ /**
+ * @ticket 39732
+ */
+ public function test_wp_update_comment_data_is_wp_error() {
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Get a comment.
+ $comments = get_comments(
+ array(
+ 'post_id' => $this->_comment_post->ID,
+ )
+ );
+ $comment = array_pop( $comments );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
+ $_POST['comment_ID'] = $comment->comment_ID;
+ $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+
+ // Simulate filter check error.
+ add_filter( 'wp_update_comment_data', array( $this, '_wp_update_comment_data_filter' ), 10, 3 );
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( 'wp_update_comment_data filter fails for this comment.' );
+ $this->_handleAjax( 'edit-comment' );
+ }
+
+ /**
+ * Blocks comments from being updated by returning WP_Error.
+ */
+ public function _wp_update_comment_data_filter( $data, $comment, $commentarr ) {
+ return new WP_Error( 'comment_wrong', 'wp_update_comment_data filter fails for this comment.', 500 );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxGetCommentsphpfromrev54721trunktestsphpunittestsajaxGetCommentsphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxGetComments.php (from rev 54721, trunk/tests/phpunit/tests/ajax/GetComments.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxGetComments.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxGetComments.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,161 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Ajax comment functionality.
+ *
+ * @package WordPress
+ * @subpackage UnitTests
+ * @since 3.4.0
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_get_comments
+ */
+class Tests_Ajax_wpAjaxGetComments extends WP_Ajax_UnitTestCase {
+
+ /**
+ * A post with at least one comment.
+ *
+ * @var mixed
+ */
+ protected static $comment_post = null;
+
+ /**
+ * A post with no comments.
+ *
+ * @var mixed
+ */
+ protected static $no_comment_post = null;
+
+ protected static $comment_ids = array();
+
+ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
+ self::$comment_post = $factory->post->create_and_get();
+ self::$comment_ids = $factory->comment->create_post_comments( self::$comment_post->ID, 5 );
+ self::$no_comment_post = $factory->post->create_and_get();
+ }
+
+ /**
+ * Gets comments as a privileged user (administrator).
+ *
+ * Expects test to pass.
+ */
+ public function test_as_admin() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'get-comments' );
+ $_POST['action'] = 'get-comments';
+ $_POST['p'] = self::$comment_post->ID;
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'get-comments' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
+
+ // Check the meta data.
+ $this->assertSame( '1', (string) $xml->response[0]->comments['position'] );
+ $this->assertSame( '0', (string) $xml->response[0]->comments['id'] );
+ $this->assertSame( 'get-comments_0', (string) $xml->response['action'] );
+
+ // Check the payload.
+ $this->assertNotEmpty( (string) $xml->response[0]->comments[0]->response_data );
+
+ // And supplemental is empty.
+ $this->assertEmpty( (string) $xml->response[0]->comments[0]->supplemental );
+ }
+
+ /**
+ * Gets comments as a non-privileged user (subscriber).
+ *
+ * Expects test to fail.
+ */
+ public function test_as_subscriber() {
+
+ // Become a subscriber.
+ $this->_setRole( 'subscriber' );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'get-comments' );
+ $_POST['action'] = 'get-comments';
+ $_POST['p'] = self::$comment_post->ID;
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'get-comments' );
+ }
+
+ /**
+ * Gets comments with a bad nonce.
+ *
+ * Expects test to fail.
+ */
+ public function test_bad_nonce() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce'] = wp_create_nonce( uniqid() );
+ $_POST['action'] = 'get-comments';
+ $_POST['p'] = self::$comment_post->ID;
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'get-comments' );
+ }
+
+ /**
+ * Gets comments for an invalid post.
+ *
+ * Bad post IDs are set to 0, this should return valid XML.
+ */
+ public function test_invalid_post() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'get-comments' );
+ $_POST['action'] = 'get-comments';
+ $_POST['p'] = 'b0rk';
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'get-comments' );
+ }
+
+ /**
+ * Gets comments for a post with no comments.
+ */
+ public function test_post_with_no_comments() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'get-comments' );
+ $_POST['action'] = 'get-comments';
+ $_POST['p'] = self::$no_comment_post->ID;
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '1' );
+ $this->_handleAjax( 'get-comments' );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxHeartbeatphpfromrev54721trunktestsphpunittestsajaxAutosavephp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxHeartbeat.php (from rev 54721, trunk/tests/phpunit/tests/ajax/Autosave.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxHeartbeat.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxHeartbeat.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,167 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Ajax save draft functionality.
+ *
+ * @package WordPress
+ * @subpackage UnitTests
+ * @since 3.4.0
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_heartbeat
+ */
+class Tests_Ajax_wpAjaxHeartbeat extends WP_Ajax_UnitTestCase {
+
+ /**
+ * Post
+ *
+ * @var mixed
+ */
+ protected $_post = null;
+
+ protected static $admin_id = 0;
+ protected static $editor_id = 0;
+ protected static $post;
+ protected static $post_id;
+
+ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
+ self::$admin_id = $factory->user->create( array( 'role' => 'administrator' ) );
+ self::$editor_id = $factory->user->create( array( 'role' => 'editor' ) );
+
+ // Set a user so the $post has 'post_author'.
+ wp_set_current_user( self::$admin_id );
+
+ self::$post_id = $factory->post->create( array( 'post_status' => 'draft' ) );
+ self::$post = get_post( self::$post_id );
+ }
+
+ /**
+ * Tests autosaving a post.
+ */
+ public function test_autosave_post() {
+ // The original post_author.
+ wp_set_current_user( self::$admin_id );
+
+ // Set up the $_POST request.
+ $md5 = md5( uniqid() );
+ $_POST = array(
+ 'action' => 'heartbeat',
+ '_nonce' => wp_create_nonce( 'heartbeat-nonce' ),
+ 'data' => array(
+ 'wp_autosave' => array(
+ 'post_id' => self::$post_id,
+ '_wpnonce' => wp_create_nonce( 'update-post_' . self::$post_id ),
+ 'post_content' => self::$post->post_content . PHP_EOL . $md5,
+ 'post_type' => 'post',
+ ),
+ ),
+ );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'heartbeat' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response, it is in heartbeat's response.
+ $response = json_decode( $this->_last_response, true );
+
+ // Ensure everything is correct.
+ $this->assertNotEmpty( $response['wp_autosave'] );
+ $this->assertTrue( $response['wp_autosave']['success'] );
+
+ // Check that the edit happened.
+ $post = get_post( self::$post_id );
+ $this->assertStringContainsString( $md5, $post->post_content );
+ }
+
+ /**
+ * Tests autosaving a locked post.
+ */
+ public function test_autosave_locked_post() {
+ // Lock the post to another user.
+ wp_set_current_user( self::$editor_id );
+ wp_set_post_lock( self::$post_id );
+
+ wp_set_current_user( self::$admin_id );
+
+ // Ensure post is locked.
+ $this->assertEquals( self::$editor_id, wp_check_post_lock( self::$post_id ) );
+
+ // Set up the $_POST request.
+ $md5 = md5( uniqid() );
+ $_POST = array(
+ 'action' => 'heartbeat',
+ '_nonce' => wp_create_nonce( 'heartbeat-nonce' ),
+ 'data' => array(
+ 'wp_autosave' => array(
+ 'post_id' => self::$post_id,
+ '_wpnonce' => wp_create_nonce( 'update-post_' . self::$post_id ),
+ 'post_content' => self::$post->post_content . PHP_EOL . $md5,
+ 'post_type' => 'post',
+ ),
+ ),
+ );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'heartbeat' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ $response = json_decode( $this->_last_response, true );
+
+ // Ensure everything is correct.
+ $this->assertNotEmpty( $response['wp_autosave'] );
+ $this->assertTrue( $response['wp_autosave']['success'] );
+
+ // Check that the original post was NOT edited.
+ $post = get_post( self::$post_id );
+ $this->assertStringNotContainsString( $md5, $post->post_content );
+
+ // Check if the autosave post was created.
+ $autosave = wp_get_post_autosave( self::$post_id, get_current_user_id() );
+ $this->assertNotEmpty( $autosave );
+ $this->assertStringContainsString( $md5, $autosave->post_content );
+ }
+
+ /**
+ * Tests with an invalid nonce.
+ */
+ public function test_with_invalid_nonce() {
+
+ wp_set_current_user( self::$admin_id );
+
+ // Set up the $_POST request.
+ $_POST = array(
+ 'action' => 'heartbeat',
+ '_nonce' => wp_create_nonce( 'heartbeat-nonce' ),
+ 'data' => array(
+ 'wp_autosave' => array(
+ 'post_id' => self::$post_id,
+ '_wpnonce' => substr( md5( uniqid() ), 0, 10 ),
+ ),
+ ),
+ );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'heartbeat' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ $response = json_decode( $this->_last_response, true );
+
+ $this->assertNotEmpty( $response['wp_autosave'] );
+ $this->assertFalse( $response['wp_autosave']['success'] );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxImageEditorphpfromrev54721trunktestsphpunittestsajaxMediaEditphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxImageEditor.php (from rev 54721, trunk/tests/phpunit/tests/ajax/MediaEdit.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxImageEditor.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxImageEditor.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,123 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Ajax media editing.
+ *
+ * @package WordPress
+ * @subpackage UnitTests
+ * @since 3.5.0
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_image_editor
+ *
+ * @requires function imagejpeg
+ */
+class Tests_Ajax_wpAjaxImageEditor extends WP_Ajax_UnitTestCase {
+
+ /**
+ * Tear down the test fixture.
+ */
+ public function tear_down() {
+ // Cleanup.
+ $this->remove_added_uploads();
+ parent::tear_down();
+ }
+
+ /**
+ * @ticket 22985
+ * @requires function imagejpeg
+ *
+ * @covers ::wp_insert_attachment
+ * @covers ::wp_save_image
+ */
+ public function testCropImageThumbnail() {
+ require_once ABSPATH . 'wp-admin/includes/image-edit.php';
+
+ $filename = DIR_TESTDATA . '/images/canola.jpg';
+ $contents = file_get_contents( $filename );
+
+ $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
+ $id = $this->_make_attachment( $upload );
+
+ $_REQUEST['action'] = 'image-editor';
+ $_REQUEST['context'] = 'edit-attachment';
+ $_REQUEST['postid'] = $id;
+ $_REQUEST['target'] = 'thumbnail';
+ $_REQUEST['do'] = 'save';
+ $_REQUEST['history'] = '[{"c":{"x":5,"y":8,"w":289,"h":322}}]';
+
+ $media_meta = wp_get_attachment_metadata( $id );
+ $this->assertArrayHasKey( 'sizes', $media_meta, 'attachment should have size data' );
+ $this->assertArrayHasKey( 'medium', $media_meta['sizes'], 'attachment should have data for medium size' );
+ $ret = wp_save_image( $id );
+
+ $media_meta = wp_get_attachment_metadata( $id );
+ $this->assertArrayHasKey( 'sizes', $media_meta, 'cropped attachment should have size data' );
+ $this->assertArrayHasKey( 'medium', $media_meta['sizes'], 'cropped attachment should have data for medium size' );
+ }
+
+ /**
+ * @ticket 32171
+ * @requires function imagejpeg
+ *
+ * @covers ::wp_insert_attachment
+ * @covers ::wp_save_image
+ */
+ public function testImageEditOverwriteConstant() {
+ define( 'IMAGE_EDIT_OVERWRITE', true );
+
+ require_once ABSPATH . 'wp-admin/includes/image-edit.php';
+
+ $filename = DIR_TESTDATA . '/images/canola.jpg';
+ $contents = file_get_contents( $filename );
+
+ $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
+ $id = $this->_make_attachment( $upload );
+
+ $_REQUEST['action'] = 'image-editor';
+ $_REQUEST['context'] = 'edit-attachment';
+ $_REQUEST['postid'] = $id;
+ $_REQUEST['target'] = 'all';
+ $_REQUEST['do'] = 'save';
+ $_REQUEST['history'] = '[{"c":{"x":5,"y":8,"w":289,"h":322}}]';
+
+ $ret = wp_save_image( $id );
+
+ $media_meta = wp_get_attachment_metadata( $id );
+ $sizes1 = $media_meta['sizes'];
+
+ $_REQUEST['history'] = '[{"c":{"x":5,"y":8,"w":189,"h":322}}]';
+
+ $ret = wp_save_image( $id );
+
+ $media_meta = wp_get_attachment_metadata( $id );
+ $sizes2 = $media_meta['sizes'];
+
+ $file_path = dirname( get_attached_file( $id ) );
+
+ $files_that_should_not_exist = array();
+
+ foreach ( $sizes1 as $key => $size ) {
+ if ( $sizes2[ $key ]['file'] !== $size['file'] ) {
+ $files_that_should_not_exist[] = $file_path . '/' . $size['file'];
+ }
+ }
+
+ if ( ! empty( $files_that_should_not_exist ) ) {
+ foreach ( $files_that_should_not_exist as $file ) {
+ $this->assertFileDoesNotExist( $file, 'IMAGE_EDIT_OVERWRITE is leaving garbage image files behind.' );
+ }
+ } else {
+ /*
+ * This assertion will always pass due to the "if" condition, but prevents this test
+ * from being marked as "risky" due to the test not performing any assertions.
+ */
+ $this->assertSame( array(), $files_that_should_not_exist );
+ }
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxInlineSavephpfromrev54721trunktestsphpunittestsajaxQuickEditphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxInlineSave.php (from rev 54721, trunk/tests/phpunit/tests/ajax/QuickEdit.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxInlineSave.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxInlineSave.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,90 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Quick Edit AJAX functionality.
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_inline_save
+ */
+class Tests_Ajax_wpAjaxInlineSave extends WP_Ajax_UnitTestCase {
+
+ /**
+ * @ticket 26948
+ *
+ * @covers ::edit_post
+ */
+ public function test_dont_process_terms_if_taxonomy_does_not_allow_show_on_quick_edit() {
+ register_taxonomy(
+ 'wptests_tax_1',
+ 'post',
+ array(
+ 'show_in_quick_edit' => false,
+ 'hierarchical' => true,
+ )
+ );
+ register_taxonomy(
+ 'wptests_tax_2',
+ 'post',
+ array(
+ 'show_in_quick_edit' => true,
+ 'hierarchical' => true,
+ )
+ );
+
+ $t1 = self::factory()->term->create(
+ array(
+ 'taxonomy' => 'wptests_tax_1',
+ )
+ );
+ $t2 = self::factory()->term->create(
+ array(
+ 'taxonomy' => 'wptests_tax_2',
+ )
+ );
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ $post = self::factory()->post->create_and_get(
+ array(
+ 'post_author' => get_current_user_id(),
+ )
+ );
+
+ // Set up a request.
+ $_POST['_inline_edit'] = wp_create_nonce( 'inlineeditnonce' );
+ $_POST['post_ID'] = $post->ID;
+ $_POST['post_type'] = $post->post_type;
+ $_POST['content'] = $post->post_content;
+ $_POST['excerpt'] = $post->post_excerpt;
+ $_POST['_status'] = $post->post_status;
+ $_POST['post_status'] = $post->post_status;
+ $_POST['screen'] = 'post';
+ $_POST['post_view'] = 'excerpt';
+ $_POST['tax_input'] = array(
+ 'wptests_tax_1' => array( $t1 ),
+ 'wptests_tax_2' => array( $t2 ),
+ );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'inline-save' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // 'wptests_tax_1' terms should have been refused.
+ $post_terms_1 = wp_get_object_terms( $post->ID, 'wptests_tax_1' );
+ $this->assertEmpty( $post_terms_1 );
+
+ // 'wptests_tax_2' terms should have been added successfully.
+ $post_terms_2 = wp_get_object_terms( $post->ID, 'wptests_tax_2' );
+ $this->assertSameSets( array( $t2 ), wp_list_pluck( $post_terms_2, 'term_id' ) );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxReplytoCommentphpfromrev54721trunktestsphpunittestsajaxReplytoCommentphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxReplytoComment.php (from rev 54721, trunk/tests/phpunit/tests/ajax/ReplytoComment.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxReplytoComment.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxReplytoComment.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,273 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Ajax comment functionality.
+ *
+ * @package WordPress
+ * @subpackage UnitTests
+ * @since 3.4.0
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_replyto_comment
+ */
+class Tests_Ajax_wpAjaxReplytoComment extends WP_Ajax_UnitTestCase {
+
+ /**
+ * A post with at least one comment.
+ *
+ * @var mixed
+ */
+ protected static $comment_post = null;
+
+ /**
+ * Draft post.
+ *
+ * @var mixed
+ */
+ protected static $draft_post = null;
+
+ protected static $comment_ids = array();
+
+ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
+ self::$comment_post = $factory->post->create_and_get();
+ self::$comment_ids = $factory->comment->create_post_comments( self::$comment_post->ID, 5 );
+ self::$draft_post = $factory->post->create_and_get( array( 'post_status' => 'draft' ) );
+ }
+
+ public function tear_down() {
+ remove_filter( 'query', array( $this, '_block_comments' ) );
+ parent::tear_down();
+ }
+
+ /**
+ * Tests reply as a privileged user (administrator).
+ *
+ * Expects test to pass.
+ */
+ public function test_as_admin() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Get a comment.
+ $comments = get_comments(
+ array(
+ 'post_id' => self::$comment_post->ID,
+ )
+ );
+ $comment = array_pop( $comments );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
+ $_POST['comment_ID'] = $comment->comment_ID;
+ $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+ $_POST['comment_post_ID'] = self::$comment_post->ID;
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'replyto-comment' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
+
+ // Check the meta data.
+ $this->assertSame( '-1', (string) $xml->response[0]->comment['position'] );
+ $this->assertGreaterThan( 0, (int) $xml->response[0]->comment['id'] );
+ $this->assertNotEmpty( (string) $xml->response['action'] );
+
+ // Check the payload.
+ $this->assertNotEmpty( (string) $xml->response[0]->comment[0]->response_data );
+
+ // And supplemental is empty.
+ $this->assertEmpty( (string) $xml->response[0]->comment[0]->supplemental );
+ }
+
+ /**
+ * Tests reply as a non-privileged user (subscriber).
+ *
+ * Expects test to fail.
+ */
+ public function test_as_subscriber() {
+
+ // Become an administrator.
+ $this->_setRole( 'subscriber' );
+
+ // Get a comment.
+ $comments = get_comments(
+ array(
+ 'post_id' => self::$comment_post->ID,
+ )
+ );
+ $comment = array_pop( $comments );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
+ $_POST['comment_ID'] = $comment->comment_ID;
+ $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+ $_POST['comment_post_ID'] = self::$comment_post->ID;
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'replyto-comment' );
+ }
+
+ /**
+ * Tests reply using a bad nonce.
+ *
+ * Expects test to fail.
+ */
+ public function test_bad_nonce() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Get a comment.
+ $comments = get_comments(
+ array(
+ 'post_id' => self::$comment_post->ID,
+ )
+ );
+ $comment = array_pop( $comments );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( uniqid() );
+ $_POST['comment_ID'] = $comment->comment_ID;
+ $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+ $_POST['comment_post_ID'] = self::$comment_post->ID;
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'replyto-comment' );
+ }
+
+ /**
+ * Tests reply to an invalid post.
+ *
+ * Expects test to fail.
+ */
+ public function test_invalid_post() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
+ $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+ $_POST['comment_post_ID'] = 123456789;
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'replyto-comment' );
+ }
+
+ /**
+ * Tests reply to a draft post.
+ *
+ * Expects test to fail.
+ */
+ public function test_with_draft_post() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
+ $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+ $_POST['comment_post_ID'] = self::$draft_post->ID;
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( 'You cannot reply to a comment on a draft post.' );
+ $this->_handleAjax( 'replyto-comment' );
+ }
+
+ /**
+ * Tests reply to a post with a simulated database failure.
+ *
+ * Expects test to fail.
+ *
+ * @global $wpdb
+ */
+ public function test_blocked_comment() {
+ global $wpdb;
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
+ $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+ $_POST['comment_post_ID'] = self::$comment_post->ID;
+
+ // Block comments from being saved, simulate a DB error.
+ add_filter( 'query', array( $this, '_block_comments' ) );
+
+ // Make the request.
+ try {
+ $wpdb->suppress_errors( true );
+ $this->_handleAjax( 'replyto-comment' );
+ $wpdb->suppress_errors( false );
+ $this->fail();
+ } catch ( WPAjaxDieStopException $e ) {
+ $wpdb->suppress_errors( false );
+ $this->assertStringContainsString( '1', $e->getMessage() );
+ }
+ }
+
+ /**
+ * Blocks comments from being saved.
+ *
+ * @param string $sql
+ * @return string
+ */
+ public function _block_comments( $sql ) {
+ global $wpdb;
+ if ( false !== strpos( $sql, $wpdb->comments ) && 0 === stripos( trim( $sql ), 'INSERT INTO' ) ) {
+ return '';
+ }
+ return $sql;
+ }
+
+ /**
+ * Tests blocking a comment from being saved on 'pre_comment_approved'.
+ *
+ * @ticket 39730
+ */
+ public function test_pre_comments_approved() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
+ $_POST['content'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+ $_POST['comment_post_ID'] = self::$comment_post->ID;
+
+ // Simulate filter check error.
+ add_filter( 'pre_comment_approved', array( $this, '_pre_comment_approved_filter' ), 10, 2 );
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( 'pre_comment_approved filter fails for new comment.' );
+ $this->_handleAjax( 'replyto-comment' );
+ }
+
+ /**
+ * Blocks comments from being saved on 'pre_comment_approved', by returning WP_Error.
+ */
+ public function _pre_comment_approved_filter( $approved, $commentdata ) {
+ return new WP_Error( 'comment_wrong', 'pre_comment_approved filter fails for new comment.', 403 );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxResponsephpfromrev54721trunktestsphpunittestsajaxResponsephp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxResponse.php (from rev 54721, trunk/tests/phpunit/tests/ajax/Response.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxResponse.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxResponse.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,108 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Testing Ajax response class
+ *
+ * @package WordPress
+ * @subpackage UnitTests
+ * @since 3.5.0
+ *
+ * @group ajax
+ *
+ * @covers WP_Ajax_Response::send
+ */
+class Tests_Ajax_wpAjaxResponse extends WP_UnitTestCase {
+
+ /**
+ * Saved error reporting level
+ *
+ * @var int
+ */
+ protected $_error_level = 0;
+
+ /**
+ * Set up the test fixture.
+ * Override wp_die(), pretend to be ajax, and suppres E_WARNINGs
+ */
+ public function set_up() {
+ parent::set_up();
+
+ add_filter( 'wp_die_ajax_handler', array( $this, 'getDieHandler' ), 1, 1 );
+ add_filter( 'wp_doing_ajax', '__return_true' );
+
+ // Suppress warnings from "Cannot modify header information - headers already sent by".
+ $this->_error_level = error_reporting();
+ error_reporting( $this->_error_level & ~E_WARNING );
+ }
+
+ /**
+ * Tear down the test fixture.
+ * Remove the wp_die() override, restore error reporting
+ */
+ public function tear_down() {
+ remove_filter( 'wp_die_ajax_handler', array( $this, 'getDieHandler' ), 1, 1 );
+ error_reporting( $this->_error_level );
+ parent::tear_down();
+ }
+
+ /**
+ * Return our callback handler
+ *
+ * @return callback
+ */
+ public function getDieHandler() {
+ return array( $this, 'dieHandler' );
+ }
+
+ /**
+ * Handler for wp_die()
+ * Don't die, just continue on.
+ *
+ * @param string $message
+ */
+ public function dieHandler( $message ) {
+ }
+
+ /**
+ * Test that charset in header matches blog_charset
+ * Note: headers_list doesn't work properly in CLI mode, fall back on
+ * xdebug_get_headers if it's available
+ * Needs a separate process to get around the headers/output from the
+ * bootstrapper
+ *
+ * @ticket 19448
+ * @runInSeparateProcess
+ * @preserveGlobalState disabled
+ * @group xdebug
+ * @requires function xdebug_get_headers
+ */
+ public function test_response_charset_in_header() {
+
+ // Generate an Ajax response.
+ ob_start();
+ $ajax_response = new WP_Ajax_Response();
+ $ajax_response->send();
+
+ // Check the header.
+ $headers = xdebug_get_headers();
+ ob_end_clean();
+
+ $this->assertContains( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), $headers );
+ }
+
+ /**
+ * Test that charset in the xml tag matches blog_charset
+ *
+ * @ticket 19448
+ */
+ public function test_response_charset_in_xml() {
+
+ // Generate an Ajax response.
+ ob_start();
+ $ajax_response = new WP_Ajax_Response();
+ $ajax_response->send();
+
+ // Check the XML tag.
+ $contents = ob_get_clean();
+ $this->assertMatchesRegularExpression( '/<\?xml\s+version=\'1.0\'\s+encoding=\'' . preg_quote( get_option( 'blog_charset' ) ) . '\'\s+standalone=\'yes\'\?>/', $contents );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxSendAttachmentToEditorphpfromrev54721trunktestsphpunittestsajaxAttachmentsphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxSendAttachmentToEditor.php (from rev 54721, trunk/tests/phpunit/tests/ajax/Attachments.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxSendAttachmentToEditor.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxSendAttachmentToEditor.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,104 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Ajax attachment handling.
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_send_attachment_to_editor
+ */
+class Tests_Ajax_wpAjaxSendAttachmentToEditor extends WP_Ajax_UnitTestCase {
+
+ /**
+ * @ticket 36578
+ *
+ * @covers ::get_image_send_to_editor
+ */
+ public function test_wp_ajax_send_attachment_to_editor_should_return_an_image() {
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ $filename = DIR_TESTDATA . '/images/canola.jpg';
+ $contents = file_get_contents( $filename );
+
+ $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
+ $attachment = $this->_make_attachment( $upload );
+
+ // Set up a default request.
+ $_POST['nonce'] = wp_create_nonce( 'media-send-to-editor' );
+ $_POST['html'] = 'Bar Baz';
+ $_POST['post_id'] = 0;
+ $_POST['attachment'] = array(
+ 'id' => $attachment,
+ 'align' => 'left',
+ 'image-size' => 'large',
+ 'image_alt' => 'Foo bar',
+ 'url' => 'http://example.com/',
+ );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'send-attachment-to-editor' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = get_image_send_to_editor( $attachment, '', '', 'left', 'http://example.com/', false, 'large', 'Foo bar' );
+
+ // Ensure everything is correct.
+ $this->assertTrue( $response['success'] );
+ $this->assertSame( $expected, $response['data'] );
+ }
+
+ /**
+ * @ticket 36578
+ * @group ms-excluded
+ */
+ public function test_wp_ajax_send_attachment_to_editor_should_return_a_link() {
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ $filename = DIR_TESTDATA . '/formatting/entities.txt';
+ $contents = file_get_contents( $filename );
+
+ $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
+ $attachment = $this->_make_attachment( $upload );
+
+ // Set up a default request.
+ $_POST['nonce'] = wp_create_nonce( 'media-send-to-editor' );
+ $_POST['html'] = 'Bar Baz';
+ $_POST['post_id'] = 0;
+ $_POST['attachment'] = array(
+ 'id' => $attachment,
+ 'post_title' => 'Foo bar',
+ 'url' => get_attachment_link( $attachment ),
+ );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'send-attachment-to-editor' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = sprintf(
+ '<a href="%s" rel="attachment wp-att-%d">Foo bar</a>',
+ get_attachment_link( $attachment ),
+ $attachment
+ );
+
+ // Ensure everything is correct.
+ $this->assertTrue( $response['success'] );
+ $this->assertSame( $expected, $response['data'] );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxUpdatePluginphpfromrev54721trunktestsphpunittestsajaxUpdatePluginphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxUpdatePlugin.php (from rev 54721, trunk/tests/phpunit/tests/ajax/UpdatePlugin.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxUpdatePlugin.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxUpdatePlugin.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,173 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Ajax handler for updating a plugin.
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_update_plugin
+ */
+class Tests_Ajax_wpAjaxUpdatePlugin extends WP_Ajax_UnitTestCase {
+
+ public function test_missing_nonce() {
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'update-plugin' );
+ }
+
+ public function test_missing_plugin() {
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+ $_POST['slug'] = 'foo';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'update-plugin' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = array(
+ 'success' => false,
+ 'data' => array(
+ 'slug' => '',
+ 'errorCode' => 'no_plugin_specified',
+ 'errorMessage' => 'No plugin specified.',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+
+ public function test_missing_slug() {
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+ $_POST['plugin'] = 'foo/bar.php';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'update-plugin' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = array(
+ 'success' => false,
+ 'data' => array(
+ 'slug' => '',
+ 'errorCode' => 'no_plugin_specified',
+ 'errorMessage' => 'No plugin specified.',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+
+ public function test_missing_capability() {
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+ $_POST['plugin'] = 'foo/bar.php';
+ $_POST['slug'] = 'foo';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'update-plugin' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = array(
+ 'success' => false,
+ 'data' => array(
+ 'update' => 'plugin',
+ 'slug' => 'foo',
+ 'oldVersion' => '',
+ 'newVersion' => '',
+ 'errorMessage' => 'Sorry, you are not allowed to update plugins for this site.',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+
+ public function test_invalid_file() {
+ $this->_setRole( 'administrator' );
+
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+ $_POST['plugin'] = '../foo/bar.php';
+ $_POST['slug'] = 'foo';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'update-plugin' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = array(
+ 'success' => false,
+ 'data' => array(
+ 'update' => 'plugin',
+ 'slug' => 'foo',
+ 'oldVersion' => '',
+ 'newVersion' => '',
+ 'errorMessage' => 'Sorry, you are not allowed to update plugins for this site.',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+
+ /**
+ * @group ms-excluded
+ */
+ public function test_update_plugin() {
+ $this->_setRole( 'administrator' );
+
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+ $_POST['plugin'] = 'hello.php';
+ $_POST['slug'] = 'hello-dolly';
+
+ // Make the request.
+ try {
+ // Prevent wp_update_plugins() from running.
+ wp_installing( true );
+ $this->_handleAjax( 'update-plugin' );
+ wp_installing( false );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = array(
+ 'success' => false,
+ 'data' => array(
+ 'update' => 'plugin',
+ 'slug' => 'hello-dolly',
+ 'oldVersion' => 'Version 1.7.2',
+ 'newVersion' => '',
+ 'plugin' => 'hello.php',
+ 'pluginName' => 'Hello Dolly',
+ 'debug' => array( 'The plugin is at the latest version.' ),
+ 'errorMessage' => 'The plugin is at the latest version.',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxUpdateThemephpfromrev54721trunktestsphpunittestsajaxManageThemesphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxUpdateTheme.php (from rev 54721, trunk/tests/phpunit/tests/ajax/ManageThemes.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxUpdateTheme.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxUpdateTheme.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,179 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Ajax handler for installing, updating, and deleting themes.
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_update_theme
+ */
+class Tests_Ajax_wpAjaxUpdateTheme extends WP_Ajax_UnitTestCase {
+ private $orig_theme_dir;
+ private $theme_root;
+
+ public function set_up() {
+ parent::set_up();
+
+ $this->theme_root = DIR_TESTDATA . '/themedir1';
+ $this->orig_theme_dir = $GLOBALS['wp_theme_directories'];
+
+ // /themes is necessary as theme.php functions assume /themes is the root if there is only one root.
+ $GLOBALS['wp_theme_directories'] = array( WP_CONTENT_DIR . '/themes', $this->theme_root );
+
+ add_filter( 'theme_root', array( $this, 'filter_theme_root' ) );
+ add_filter( 'stylesheet_root', array( $this, 'filter_theme_root' ) );
+ add_filter( 'template_root', array( $this, 'filter_theme_root' ) );
+
+ wp_clean_themes_cache();
+ unset( $GLOBALS['wp_themes'] );
+ }
+
+ public function tear_down() {
+ $GLOBALS['wp_theme_directories'] = $this->orig_theme_dir;
+ remove_filter( 'theme_root', array( $this, 'filter_theme_root' ) );
+ remove_filter( 'stylesheet_root', array( $this, 'filter_theme_root' ) );
+ remove_filter( 'template_root', array( $this, 'filter_theme_root' ) );
+ wp_clean_themes_cache();
+ unset( $GLOBALS['wp_themes'] );
+
+ parent::tear_down();
+ }
+
+ /**
+ * Replace the normal theme root dir with our pre-made test dir.
+ */
+ public function filter_theme_root() {
+ return $this->theme_root;
+ }
+
+ public function test_missing_slug() {
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'update-theme' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = array(
+ 'success' => false,
+ 'data' => array(
+ 'slug' => '',
+ 'errorCode' => 'no_theme_specified',
+ 'errorMessage' => 'No theme specified.',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+
+ public function test_missing_capability() {
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+ $_POST['slug'] = 'foo';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'update-theme' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = array(
+ 'success' => false,
+ 'data' => array(
+ 'update' => 'theme',
+ 'slug' => 'foo',
+ 'oldVersion' => '',
+ 'newVersion' => '',
+ 'errorMessage' => 'Sorry, you are not allowed to update themes for this site.',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+
+ /**
+ * @group ms-excluded
+ */
+ public function test_update_theme() {
+ $this->_setRole( 'administrator' );
+
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+ $_POST['slug'] = 'twentyten';
+
+ // Make the request.
+ try {
+
+ // Prevent wp_update_themes() from running.
+ wp_installing( true );
+ $this->_handleAjax( 'update-theme' );
+ wp_installing( false );
+
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $theme = wp_get_theme( 'twentyten' );
+ $expected = array(
+ 'success' => false,
+ 'data' => array(
+ 'update' => 'theme',
+ 'slug' => 'twentyten',
+ 'oldVersion' => $theme->get( 'Version' ),
+ 'newVersion' => '',
+ 'debug' => array( 'The theme is at the latest version.' ),
+ 'errorMessage' => 'The theme is at the latest version.',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+
+ /**
+ * @group ms-excluded
+ */
+ public function test_uppercase_theme_slug() {
+ $this->_setRole( 'administrator' );
+
+ $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' );
+ $_POST['slug'] = 'camelCase';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'update-theme' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Get the response.
+ $response = json_decode( $this->_last_response, true );
+
+ $expected = array(
+ 'success' => false,
+ 'data' => array(
+ 'update' => 'theme',
+ 'slug' => 'camelCase',
+ 'oldVersion' => '1.0',
+ 'newVersion' => '',
+ 'debug' => array( 'The theme is at the latest version.' ),
+ 'errorMessage' => 'The theme is at the latest version.',
+ ),
+ );
+
+ $this->assertSameSets( $expected, $response );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxWpCompressionTestphpfromrev54721trunktestsphpunittestsajaxCompressionphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxWpCompressionTest.php (from rev 54721, trunk/tests/phpunit/tests/ajax/Compression.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxWpCompressionTest.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxWpCompressionTest.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,225 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Admin Ajax functions to be tested.
+ */
+require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';
+
+/**
+ * Testing Ajax compression test functionality.
+ *
+ * @package WordPress
+ * @subpackage UnitTests
+ * @since 3.4.0
+ *
+ * @group ajax
+ *
+ * @covers ::wp_ajax_wp_compression_test
+ */
+class Tests_Ajax_wpAjaxWpCompressionTest extends WP_Ajax_UnitTestCase {
+
+ /**
+ * Test as a logged out user
+ */
+ public function test_logged_out() {
+ $this->logout();
+
+ // Set up a default request.
+ $_GET['test'] = 1;
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'wp-compression-test' );
+ }
+
+ /**
+ * Fetch the test text
+ */
+ public function test_text() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_GET['test'] = 1;
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'wp-compression-test' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Ensure we found the right match.
+ $this->assertStringContainsString( 'wpCompressionTest', $this->_last_response );
+ }
+
+ /**
+ * Fetch the test text (gzdeflate)
+ *
+ * @requires function gzdeflate
+ */
+ public function test_gzdeflate() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_GET['test'] = 2;
+ $_SERVER['HTTP_ACCEPT_ENCODING'] = 'deflate';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'wp-compression-test' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Ensure we found the right match.
+ $this->assertStringContainsString( 'wpCompressionTest', gzinflate( $this->_last_response ) );
+ }
+
+ /**
+ * Fetch the test text (gzencode)
+ *
+ * @requires function gzencode
+ */
+ public function test_gzencode() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_GET['test'] = 2;
+ $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip';
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'wp-compression-test' );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ // Ensure we found the right match.
+ $this->assertStringContainsString( 'wpCompressionTest', $this->_gzdecode( $this->_last_response ) );
+ }
+
+ /**
+ * Fetch the test text (unknown encoding)
+ */
+ public function test_unknown_encoding() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_GET['test'] = 2;
+ $_SERVER['HTTP_ACCEPT_ENCODING'] = 'unknown';
+
+ // Make the request.
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ $this->_handleAjax( 'wp-compression-test' );
+ }
+
+ /**
+ * Set the 'can_compress_scripts' site option to true
+ */
+ public function test_set_yes() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_GET['test'] = 'yes';
+
+ // Set the option to false.
+ update_site_option( 'can_compress_scripts', 0 );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'wp-compression-test' );
+ } catch ( WPAjaxDieStopException $e ) {
+ unset( $e );
+ }
+
+ // Check the site option is not changed due to lack of nonce.
+ $this->assertSame( 0, get_site_option( 'can_compress_scripts' ) );
+
+ // Add a nonce.
+ $_GET['_ajax_nonce'] = wp_create_nonce( 'update_can_compress_scripts' );
+
+ // Retry the request.
+ try {
+ $this->_handleAjax( 'wp-compression-test' );
+ } catch ( WPAjaxDieStopException $e ) {
+ unset( $e );
+ }
+
+ // Check the site option is changed.
+ $this->assertSame( 1, get_site_option( 'can_compress_scripts' ) );
+ }
+
+ /**
+ * Set the 'can_compress_scripts' site option to false
+ */
+ public function test_set_no() {
+
+ // Become an administrator.
+ $this->_setRole( 'administrator' );
+
+ // Set up a default request.
+ $_GET['test'] = 'no';
+
+ // Set the option to true.
+ update_site_option( 'can_compress_scripts', 1 );
+
+ // Make the request.
+ try {
+ $this->_handleAjax( 'wp-compression-test' );
+ } catch ( WPAjaxDieStopException $e ) {
+ unset( $e );
+ }
+
+ // Check the site option is not changed due to lack of nonce.
+ $this->assertSame( 1, get_site_option( 'can_compress_scripts' ) );
+
+ // Add a nonce.
+ $_GET['_ajax_nonce'] = wp_create_nonce( 'update_can_compress_scripts' );
+
+ // Retry the request.
+ try {
+ $this->_handleAjax( 'wp-compression-test' );
+ } catch ( WPAjaxDieStopException $e ) {
+ unset( $e );
+ }
+
+ // Check the site option is changed.
+ $this->assertSame( 0, get_site_option( 'can_compress_scripts' ) );
+ }
+
+ /**
+ * Undo gzencode. This is ugly, but there's no stock gzdecode() function.
+ *
+ * @param string $encoded_data
+ * @return string
+ */
+ protected function _gzdecode( $encoded_data ) {
+
+ // Save the encoded data to a temp file.
+ $file = wp_tempnam( 'gzdecode' );
+ file_put_contents( $file, $encoded_data );
+
+ // Flush it to the output buffer and delete the temp file.
+ ob_start();
+ readgzfile( $file );
+ unlink( $file );
+
+ // Save the data stop buffering.
+ $data = ob_get_clean();
+
+ // Done.
+ return $data;
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxWpPrivacyErasePersonalDataphpfromrev54721trunktestsphpunittestsajaxPrivacyErasePersonalDataphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxWpPrivacyErasePersonalData.php (from rev 54721, trunk/tests/phpunit/tests/ajax/PrivacyErasePersonalData.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxWpPrivacyErasePersonalData.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxWpPrivacyErasePersonalData.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,839 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Testing Ajax handler for erasing personal data.
+ *
+ * @package WordPress\UnitTests
+ * @since 5.2.0
+ */
+
+/**
+ * Tests_Ajax_PrivacyExportPersonalData class.
+ *
+ * @since 5.2.0
+ *
+ * @group ajax
+ * @group privacy
+ *
+ * @covers ::wp_ajax_wp_privacy_erase_personal_data
+ */
+class Tests_Ajax_wpAjaxWpPrivacyErasePersonalData extends WP_Ajax_UnitTestCase {
+
+ /**
+ * User Request ID.
+ *
+ * @since 5.2.0
+ *
+ * @var int $request_id
+ */
+ protected static $request_id;
+
+ /**
+ * User Request Email.
+ *
+ * @since 5.2.0
+ *
+ * @var string $request_email
+ */
+ protected static $request_email;
+
+ /**
+ * Ajax Action.
+ *
+ * @since 5.2.0
+ *
+ * @var string $action
+ */
+ protected static $action;
+
+ /**
+ * Eraser Index.
+ *
+ * @since 5.2.0
+ *
+ * @var int $eraser
+ */
+ protected static $eraser;
+
+ /**
+ * Eraser Key.
+ *
+ * @since 5.2.0
+ *
+ * @var string $eraser_key
+ */
+ protected static $eraser_key;
+
+ /**
+ * Eraser Friendly Name.
+ *
+ * @since 5.2.0
+ *
+ * @var string $eraser_friendly_name
+ */
+ protected static $eraser_friendly_name;
+
+ /**
+ * Page Index.
+ *
+ * @since 5.2.0
+ *
+ * @var int $page
+ */
+ protected static $page;
+
+ /**
+ * Last response parsed.
+ *
+ * @since 5.2.0
+ *
+ * @var array $_last_response_parsed
+ */
+ protected $_last_response_parsed;
+
+ /**
+ * An array key in the test eraser to unset.
+ *
+ * @since 5.2.0
+ *
+ * @var string $key_to_unset
+ */
+ protected $key_to_unset;
+
+ /**
+ * A value to change the test eraser callback to.
+ *
+ * @since 5.2.0
+ *
+ * @var string $new_callback_value
+ */
+ protected $new_callback_value;
+
+ /**
+ * Create user erase request fixtures.
+ *
+ * @param WP_UnitTest_Factory $factory Factory.
+ */
+ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
+ self::$request_email = 'requester@example.com';
+ self::$request_id = wp_create_user_request( self::$request_email, 'remove_personal_data' );
+ self::$action = 'wp-privacy-erase-personal-data';
+ self::$eraser = 1;
+ self::$eraser_key = 'custom-eraser';
+ self::$eraser_friendly_name = 'Custom Eraser';
+ self::$page = 1;
+ }
+
+ /**
+ * Register a custom personal data eraser.
+ */
+ public function set_up() {
+ parent::set_up();
+
+ $this->key_to_unset = '';
+
+ // Make sure the erasers response is not modified and avoid sending emails.
+ remove_all_filters( 'wp_privacy_personal_data_erasure_page' );
+ remove_all_actions( 'wp_privacy_personal_data_erased' );
+
+ // Only use our custom privacy personal data eraser.
+ remove_all_filters( 'wp_privacy_personal_data_erasers' );
+ add_filter( 'wp_privacy_personal_data_erasers', array( $this, 'register_custom_personal_data_eraser' ) );
+
+ $this->_setRole( 'administrator' );
+ // `erase_others_personal_data` meta cap in Multisite installation is only granted to those with `manage_network` capability.
+ if ( is_multisite() ) {
+ grant_super_admin( get_current_user_id() );
+ }
+ }
+
+ /**
+ * Clean up after each test method.
+ */
+ public function tear_down() {
+ remove_filter( 'wp_privacy_personal_data_erasers', array( $this, 'register_custom_personal_data_eraser' ) );
+ $this->new_callback_value = '';
+
+ if ( is_multisite() ) {
+ revoke_super_admin( get_current_user_id() );
+ }
+
+ parent::tear_down();
+ }
+
+ /**
+ * Helper method for changing the test eraser's callback function.
+ *
+ * @param string|array $callback New test eraser callback index value.
+ */
+ protected function _set_eraser_callback( $callback ) {
+ $this->new_callback_value = $callback;
+ add_filter( 'wp_privacy_personal_data_erasers', array( $this, 'filter_eraser_callback_value' ), 20 );
+ }
+
+ /**
+ * Change the test eraser callback to a specified value.
+ *
+ * @since 5.2.0
+ *
+ * @param array $erasers List of data erasers.
+ *
+ * @return array Array of data erasers.
+ */
+ public function filter_eraser_callback_value( $erasers ) {
+ $erasers[ self::$eraser_key ]['callback'] = $this->new_callback_value;
+
+ return $erasers;
+ }
+
+ /**
+ * Helper method for unsetting an array index in the test eraser.
+ *
+ * @param string|bool $key Test eraser key to unset.
+ */
+ protected function _unset_eraser_key( $key ) {
+ $this->key_to_unset = $key;
+ add_filter( 'wp_privacy_personal_data_erasers', array( $this, 'filter_unset_eraser_index' ), 20 );
+ }
+
+ /**
+ * Unsets an array key in the test eraser.
+ *
+ * If the key is false, the eraser is set to false.
+ *
+ * @since 5.2.0
+ *
+ * @param array $erasers Erasers.
+ *
+ * @return array Erasers.
+ */
+ public function filter_unset_eraser_index( $erasers ) {
+ if ( false === $this->key_to_unset ) {
+ $erasers[ self::$eraser_key ] = false;
+ } elseif ( ! empty( $this->key_to_unset ) ) {
+ unset( $erasers[ self::$eraser_key ][ $this->key_to_unset ] );
+ }
+
+ return $erasers;
+ }
+
+ /**
+ * Helper method for erasing a key from the eraser response.
+ *
+ * @since 5.2.0
+ *
+ * @param array $key Response key to unset.
+ */
+ protected function _unset_response_key( $key ) {
+ $this->key_to_unset = $key;
+ $this->_set_eraser_callback( array( $this, 'filter_unset_response_index' ) );
+ }
+
+ /**
+ * Unsets an array index in a response.
+ *
+ * @since 5.2.0
+ *
+ * @param string $email_address The requester's email address.
+ * @param int $page Page number.
+ *
+ * @return array Export data.
+ */
+ public function filter_unset_response_index( $email_address, $page = 1 ) {
+ $response = $this->callback_personal_data_eraser( $email_address, $page );
+
+ if ( ! empty( $this->key_to_unset ) ) {
+ unset( $response[ $this->key_to_unset ] );
+ }
+
+ return $response;
+ }
+
+ /**
+ * The function should send an error when the request ID is missing.
+ *
+ * @since 5.2.0
+ *
+ * @ticket 43438
+ */
+ public function test_error_when_missing_request_id() {
+ $this->assertNotWPError( self::$request_id );
+
+ // Set up a request.
+ $this->_make_ajax_call(
+ array(
+ 'id' => null, // Missing request ID.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Missing request ID.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the request ID is less than 1.
+ *
+ * @since 5.2.0
+ *
+ * @ticket 43438
+ */
+ public function test_error_when_request_id_invalid() {
+ $this->assertNotWPError( self::$request_id );
+
+ // Set up a request.
+ $this->_make_ajax_call(
+ array(
+ 'id' => -1, // Invalid request ID.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Invalid request ID.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the current user is missing required capabilities.
+ *
+ * @since 5.2.0
+ *
+ * @ticket 43438
+ */
+ public function test_error_when_current_user_missing_required_capabilities() {
+ $this->_setRole( 'author' );
+
+ $this->assertFalse( current_user_can( 'erase_others_personal_data' ) );
+ $this->assertFalse( current_user_can( 'delete_users' ) );
+
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Sorry, you are not allowed to perform this action.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * Test requests do not succeed on multisite when the current user is not a network admin.
+ *
+ * @ticket 43438
+ * @group multisite
+ * @group ms-required
+ */
+ public function test_error_when_current_user_missing_required_capabilities_multisite() {
+ revoke_super_admin( get_current_user_id() );
+
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Sorry, you are not allowed to perform this action.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the nonce does not validate.
+ *
+ * @since 5.2.0
+ */
+ public function test_failure_with_invalid_nonce() {
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+
+ $this->_make_ajax_call(
+ array(
+ 'security' => 'invalid-nonce',
+ )
+ );
+ }
+
+ /**
+ * The function should send an error when the request type is incorrect.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_incorrect_request_type() {
+ $request_id = wp_create_user_request(
+ 'export-request@example.com',
+ 'export_personal_data' // Incorrect request type, expects 'remove_personal_data'.
+ );
+
+ $this->_make_ajax_call(
+ array(
+ 'security' => wp_create_nonce( 'wp-privacy-erase-personal-data-' . $request_id ),
+ 'id' => $request_id,
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Invalid request type.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the request email is invalid.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_invalid_email() {
+ wp_update_post(
+ array(
+ 'ID' => self::$request_id,
+ 'post_title' => '', // Invalid requester's email address.
+ )
+ );
+
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Invalid email address in request.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the eraser index is missing.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_missing_eraser_index() {
+ $this->_make_ajax_call(
+ array(
+ 'eraser' => null, // Missing eraser index.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Missing eraser index.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the page index is missing.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_missing_page_index() {
+ $this->_make_ajax_call(
+ array(
+ 'page' => null, // Missing page index.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Missing page index.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the eraser index is negative.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_negative_eraser_index() {
+ $this->_make_ajax_call(
+ array(
+ 'eraser' => -1, // Negative eraser index.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Eraser index cannot be less than one.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the eraser index is out of range.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_eraser_index_out_of_range() {
+ $this->_make_ajax_call(
+ array(
+ 'eraser' => PHP_INT_MAX, // Out of range eraser index.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Eraser index is out of range.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the page index is less than one.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_page_index_less_than_one() {
+ $this->_make_ajax_call(
+ array(
+ 'page' => 0, // Page index less than one.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Page index cannot be less than one.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when an eraser is not an array.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_eraser_not_array() {
+ $this->_unset_eraser_key( false );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Expected an array describing the eraser at index %s.',
+ self::$eraser
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * The function should send an error when an eraser is missing a friendly name.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_eraser_missing_friendly_name() {
+ $this->_unset_eraser_key( 'eraser_friendly_name' );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Eraser array at index %s does not include a friendly name.',
+ self::$eraser
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * The function should send an error when an eraser is missing a callback.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_eraser_missing_callback() {
+ $this->_unset_eraser_key( 'callback' );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Eraser does not include a callback: %s.',
+ self::$eraser_friendly_name
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * The function should send an error when an eraser, at a given index, has an invalid callback.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_eraser_index_invalid_callback() {
+ $this->_set_eraser_callback( false );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Eraser callback is not valid: %s.',
+ self::$eraser_friendly_name
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * The function should send an error when an eraser, at a given index, is missing an array response.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_eraser_index_invalid_response() {
+ $this->_set_eraser_callback( '__return_null' );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Did not receive array from %1$s eraser (index %2$d).',
+ self::$eraser_friendly_name,
+ self::$eraser
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * The function should send an error when missing an items_removed index.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_eraser_items_removed_missing() {
+ $this->_unset_response_key( 'items_removed' );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Expected items_removed key in response array from %1$s eraser (index %2$d).',
+ self::$eraser_friendly_name,
+ self::$eraser
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * The function should send an error when missing an items_retained index.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_eraser_items_retained_missing() {
+ $this->_unset_response_key( 'items_retained' );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Expected items_retained key in response array from %1$s eraser (index %2$d).',
+ self::$eraser_friendly_name,
+ self::$eraser
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * The function should send an error when missing a messages index.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_eraser_messages_missing() {
+ $this->_unset_response_key( 'messages' );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Expected messages key in response array from %1$s eraser (index %2$d).',
+ self::$eraser_friendly_name,
+ self::$eraser
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * The function should send an error when the messages index is not an array.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_eraser_messages_not_array() {
+ $this->_set_eraser_callback( array( $this, 'filter_response_messages_invalid' ) );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Expected messages key to reference an array in response array from %1$s eraser (index %2$d).',
+ self::$eraser_friendly_name,
+ self::$eraser
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * Change the messages index to an invalid value (not an array).
+ *
+ * @since 5.2.0
+ *
+ * @param string $email_address The requester's email address.
+ * @param int $page Page number.
+ *
+ * @return array Export data.
+ */
+ public function filter_response_messages_invalid( $email_address, $page = 1 ) {
+ $response = $this->callback_personal_data_eraser( $email_address, $page );
+ $response['messages'] = true;
+
+ return $response;
+ }
+
+ /**
+ * The function should send an error when an eraser is missing 'done' in array response.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_eraser_missing_done_response() {
+ $this->_unset_response_key( 'done' );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Expected done flag in response array from %1$s eraser (index %2$d).',
+ self::$eraser_friendly_name,
+ self::$eraser
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * The function should successfully send erasers response data when the current user has the required
+ * capabilities.
+ *
+ * @since 5.2.0
+ *
+ * @ticket 43438
+ */
+ public function test_success_when_current_user_has_required_capabilities() {
+ $this->assertTrue( current_user_can( 'erase_others_personal_data' ) );
+ $this->assertTrue( current_user_can( 'delete_users' ) );
+
+ $this->_make_ajax_call();
+
+ $this->assertSame(
+ sprintf( 'A message regarding retained data for %s.', self::$request_email ),
+ $this->_last_response_parsed['data']['messages'][0]
+ );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertTrue( $this->_last_response_parsed['data']['items_removed'] );
+ $this->assertTrue( $this->_last_response_parsed['data']['items_retained'] );
+ $this->assertTrue( $this->_last_response_parsed['data']['done'] );
+ }
+
+ /**
+ * The function should successfully send erasers response data when no items to erase.
+ *
+ * @since 5.2.0
+ *
+ * @ticket 43438
+ */
+ public function test_success_when_no_items_to_erase() {
+
+ $this->_make_ajax_call( array( 'page' => 2 ) );
+
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertFalse( $this->_last_response_parsed['data']['items_removed'] );
+ $this->assertFalse( $this->_last_response_parsed['data']['items_retained'] );
+ $this->assertEmpty( $this->_last_response_parsed['data']['messages'] );
+ $this->assertTrue( $this->_last_response_parsed['data']['done'] );
+ }
+
+ /**
+ * Test that the function's output should be filterable with the `wp_privacy_personal_data_erasure_page` filter.
+ *
+ * @since 5.2.0
+ */
+ public function test_output_should_be_filterable() {
+ add_filter( 'wp_privacy_personal_data_erasure_page', array( $this, 'filter_eraser_data_response' ), 20, 6 );
+ $this->_make_ajax_call();
+
+ $expected_new_index = self::$request_email . '-' . self::$request_id . '-' . self::$eraser_key;
+
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'filtered removed', $this->_last_response_parsed['data']['items_removed'] );
+ $this->assertSame( 'filtered retained', $this->_last_response_parsed['data']['items_retained'] );
+ $this->assertSame( array( 'filtered messages' ), $this->_last_response_parsed['data']['messages'] );
+ $this->assertSame( 'filtered done', $this->_last_response_parsed['data']['done'] );
+ $this->assertSame( $expected_new_index, $this->_last_response_parsed['data']['new_index'] );
+ }
+
+ /**
+ * Filters the eraser response.
+ *
+ * @since 5.2.0
+ *
+ * @param array $response The personal data for the given eraser and page.
+ * @param int $eraser_index The index of the eraser that provided this data.
+ * @param string $email_address The email address associated with this personal data.
+ * @param int $page The page for this response.
+ * @param int $request_id The privacy request post ID associated with this request.
+ * @param string $eraser_key The key (slug) of the eraser that provided this data.
+ *
+ * @return array Filtered erase response.
+ */
+ public function filter_eraser_data_response( $response, $eraser_index, $email_address, $page, $request_id, $eraser_key ) {
+ $response['items_removed'] = 'filtered removed';
+ $response['items_retained'] = 'filtered retained';
+ $response['messages'] = array( 'filtered messages' );
+ $response['done'] = 'filtered done';
+ $response['new_index'] = $email_address . '-' . $request_id . '-' . $eraser_key;
+
+ return $response;
+ }
+
+ /**
+ * Register handler for a custom personal data eraser.
+ *
+ * @since 5.2.0
+ *
+ * @param array $erasers An array of personal data erasers.
+ *
+ * @return array An array of personal data erasers.
+ */
+ public function register_custom_personal_data_eraser( $erasers ) {
+ $erasers[ self::$eraser_key ] = array(
+ 'eraser_friendly_name' => self::$eraser_friendly_name,
+ 'callback' => array( $this, 'callback_personal_data_eraser' ),
+ );
+ return $erasers;
+ }
+
+ /**
+ * Custom Personal Data Eraser.
+ *
+ * @since 5.2.0
+ *
+ * @param string $email_address The comment author email address.
+ * @param int $page Page number.
+ *
+ * @return array Erase data.
+ */
+ public function callback_personal_data_eraser( $email_address, $page = 1 ) {
+ if ( 1 === $page ) {
+ return array(
+ 'items_removed' => true,
+ 'items_retained' => true,
+ 'messages' => array( sprintf( 'A message regarding retained data for %s.', $email_address ) ),
+ 'done' => true,
+ );
+ }
+
+ return array(
+ 'items_removed' => false,
+ 'items_retained' => false,
+ 'messages' => array(),
+ 'done' => true,
+ );
+ }
+
+ /**
+ * Helper function for Ajax handler.
+ *
+ * @since 5.2.0
+ *
+ * @param array $args Ajax request arguments.
+ */
+ protected function _make_ajax_call( $args = array() ) {
+ $this->_last_response_parsed = null;
+ $this->_last_response = '';
+
+ $defaults = array(
+ 'action' => self::$action,
+ 'security' => wp_create_nonce( self::$action . '-' . self::$request_id ),
+ 'page' => self::$page,
+ 'id' => self::$request_id,
+ 'eraser' => self::$eraser,
+ );
+
+ $_POST = wp_parse_args( $args, $defaults );
+
+ try {
+ $this->_handleAjax( self::$action );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ if ( $this->_last_response ) {
+ $this->_last_response_parsed = json_decode( $this->_last_response, true );
+ }
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpAjaxWpPrivacyExportPersonalDataphpfromrev54721trunktestsphpunittestsajaxPrivacyExportPersonalDataphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpAjaxWpPrivacyExportPersonalData.php (from rev 54721, trunk/tests/phpunit/tests/ajax/PrivacyExportPersonalData.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpAjaxWpPrivacyExportPersonalData.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpAjaxWpPrivacyExportPersonalData.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,842 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Testing Ajax handler for exporting personal data.
+ *
+ * @package WordPress\UnitTests
+ * @since 5.2.0
+ */
+
+/**
+ * Tests_Ajax_PrivacyExportPersonalData class.
+ *
+ * @since 5.2.0
+ *
+ * @group ajax
+ * @group privacy
+ *
+ * @covers ::wp_ajax_wp_privacy_export_personal_data
+ */
+class Tests_Ajax_wpAjaxWpPrivacyExportPersonalData extends WP_Ajax_UnitTestCase {
+
+ /**
+ * User Request ID.
+ *
+ * @since 5.2.0
+ *
+ * @var int $request_id
+ */
+ protected static $request_id;
+
+ /**
+ * User Request Email.
+ *
+ * @since 5.2.0
+ *
+ * @var string $request_email
+ */
+ protected static $request_email;
+
+ /**
+ * Ajax Action.
+ *
+ * @since 5.2.0
+ *
+ * @var string $action
+ */
+ protected static $action;
+
+ /**
+ * Exporter Index.
+ *
+ * @since 5.2.0
+ *
+ * @var int $exporter
+ */
+ protected static $exporter;
+
+ /**
+ * Exporter Key.
+ *
+ * @since 5.2.0
+ *
+ * @var string $exporter_key
+ */
+ protected static $exporter_key;
+
+ /**
+ * Exporter Friendly Name.
+ *
+ * @since 5.2.0
+ *
+ * @var string $exporter_friendly_name
+ */
+ protected static $exporter_friendly_name;
+
+ /**
+ * Page Index.
+ *
+ * @since 5.2.0
+ *
+ * @var int $page
+ */
+ protected static $page;
+
+ /**
+ * Send As Email.
+ *
+ * @since 5.2.0
+ *
+ * @var bool $send_as_email
+ */
+ protected static $send_as_email;
+
+ /**
+ * Last response parsed.
+ *
+ * @since 5.2.0
+ *
+ * @var array $_last_response_parsed
+ */
+ protected $_last_response_parsed;
+
+ /**
+ * An array key in the test exporter to unset.
+ *
+ * @since 5.2.0
+ *
+ * @var string $key_to_unset
+ */
+ protected $key_to_unset;
+
+ /**
+ * A value to change the test exporter callback to.
+ *
+ * @since 5.2.0
+ *
+ * @var string $new_callback_value
+ */
+ protected $new_callback_value;
+
+ /**
+ * Create user export request fixtures.
+ *
+ * @since 5.2.0
+ *
+ * @param WP_UnitTest_Factory $factory Factory.
+ */
+ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
+ self::$request_email = 'requester@example.com';
+ self::$request_id = wp_create_user_request( self::$request_email, 'export_personal_data' );
+ self::$action = 'wp-privacy-export-personal-data';
+ self::$exporter = 1;
+ self::$exporter_key = 'custom-exporter';
+ self::$exporter_friendly_name = 'Custom Exporter';
+ self::$page = 1;
+ self::$send_as_email = false;
+ }
+
+ /**
+ * Setup before each test method.
+ *
+ * @since 5.2.0
+ */
+ public function set_up() {
+ parent::set_up();
+
+ $this->key_to_unset = '';
+ $this->new_callback_value = '';
+
+ // Make sure the exporter response is not modified and avoid e.g. writing export file to disk.
+ remove_all_filters( 'wp_privacy_personal_data_export_page' );
+
+ // Only use our custom privacy personal data exporter.
+ remove_all_filters( 'wp_privacy_personal_data_exporters' );
+ add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'filter_register_custom_personal_data_exporter' ) );
+
+ $this->_setRole( 'administrator' );
+ // `export_others_personal_data` meta cap in Multisite installation is only granted to those with `manage_network` capability.
+ if ( is_multisite() ) {
+ grant_super_admin( get_current_user_id() );
+ }
+ }
+
+ /**
+ * Clean up after each test method.
+ */
+ public function tear_down() {
+ remove_filter( 'wp_privacy_personal_data_exporters', array( $this, 'filter_register_custom_personal_data_exporter' ) );
+
+ if ( is_multisite() ) {
+ revoke_super_admin( get_current_user_id() );
+ }
+ parent::tear_down();
+ }
+
+ /**
+ * Helper method for changing the test exporter's callback function.
+ *
+ * @param string|array $callback New test exporter callback function.
+ */
+ protected function _set_exporter_callback( $callback ) {
+ $this->new_callback_value = $callback;
+ add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'filter_exporter_callback_value' ), 20 );
+ }
+
+ /**
+ * Change the test exporter callback to a specified value.
+ *
+ * @since 5.2.0
+ *
+ * @param array $exporters List of data exporters.
+ * @return array List of data exporters.
+ */
+ public function filter_exporter_callback_value( $exporters ) {
+ $exporters[ self::$exporter_key ]['callback'] = $this->new_callback_value;
+
+ return $exporters;
+ }
+
+ /**
+ * Helper method for unsetting an array index in the test exporter.
+ *
+ * @param string $key Test exporter key to unset.
+ */
+ protected function _unset_exporter_key( $key ) {
+ $this->key_to_unset = $key;
+ add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'filter_unset_exporter_key' ), 20 );
+ }
+
+ /**
+ * Unset a specified key in the test exporter array.
+ *
+ * @param array $exporters List of data exporters.
+ *
+ * @return array List of data exporters.
+ */
+ public function filter_unset_exporter_key( $exporters ) {
+ if ( false === $this->key_to_unset ) {
+ $exporters[ self::$exporter_key ] = false;
+ } elseif ( ! empty( $this->key_to_unset ) ) {
+ unset( $exporters[ self::$exporter_key ][ $this->key_to_unset ] );
+ }
+
+ return $exporters;
+ }
+
+ /**
+ * The function should send an error when the request ID is missing.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_missing_request_id() {
+ $this->_make_ajax_call(
+ array(
+ 'id' => null, // Missing request ID.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Missing request ID.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the request ID is less than 1.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_invalid_id() {
+ $this->_make_ajax_call(
+ array(
+ 'id' => -1, // Invalid request ID, less than 1.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Invalid request ID.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the current user is missing the required capability.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_current_user_missing_required_capability() {
+ $this->_setRole( 'author' );
+
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertFalse( current_user_can( 'export_others_personal_data' ) );
+ $this->assertSame( 'Sorry, you are not allowed to perform this action.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * Test requests do not succeed on multisite when the current user is not a network admin.
+ *
+ * @ticket 43438
+ * @group multisite
+ * @group ms-required
+ */
+ public function test_error_when_current_user_missing_required_capability_multisite() {
+ revoke_super_admin( get_current_user_id() );
+
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Sorry, you are not allowed to perform this action.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the nonce does not validate.
+ *
+ * @since 5.2.0
+ */
+ public function test_failure_with_invalid_nonce() {
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+
+ $this->_make_ajax_call(
+ array(
+ 'security' => 'invalid-nonce',
+ )
+ );
+ }
+
+ /**
+ * The function should send an error when the request type is incorrect.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_incorrect_request_type() {
+ $request_id = wp_create_user_request(
+ 'erase-request@example.com',
+ 'remove_personal_data' // Incorrect request type, expects 'export_personal_data'.
+ );
+
+ $this->_make_ajax_call(
+ array(
+ 'security' => wp_create_nonce( 'wp-privacy-export-personal-data-' . $request_id ),
+ 'id' => $request_id,
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Invalid request type.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the requester's email address is invalid.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_invalid_email_address() {
+ wp_update_post(
+ array(
+ 'ID' => self::$request_id,
+ 'post_title' => '', // Invalid requester's email address.
+ )
+ );
+
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'A valid email address must be given.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the exporter index is missing.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_missing_exporter_index() {
+ $this->_make_ajax_call(
+ array(
+ 'exporter' => null, // Missing exporter index.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Missing exporter index.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the page index is missing.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_missing_page_index() {
+ $this->_make_ajax_call(
+ array(
+ 'page' => null, // Missing page index.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Missing page index.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when an exporter has improperly used the `wp_privacy_personal_data_exporters` filter.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_exporter_has_improperly_used_exporters_filter() {
+ // Improper filter usage: returns false instead of an expected array.
+ add_filter( 'wp_privacy_personal_data_exporters', '__return_false', 999 );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'An exporter has improperly used the registration filter.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the exporter index is negative.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_negative_exporter_index() {
+ $this->_make_ajax_call(
+ array(
+ 'exporter' => -1, // Negative exporter index.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Exporter index cannot be negative.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the exporter index is out of range.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_exporter_index_out_of_range() {
+ $this->_make_ajax_call(
+ array(
+ 'exporter' => PHP_INT_MAX, // Out of range exporter index.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Exporter index is out of range.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when the page index is less than one.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_page_index_less_than_one() {
+ $this->_make_ajax_call(
+ array(
+ 'page' => 0, // Page index less than one.
+ )
+ );
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'Page index cannot be less than one.', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * The function should send an error when an exporter is not an array.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_exporter_not_array() {
+ $this->_unset_exporter_key( false );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Expected an array describing the exporter at index %s.',
+ self::$exporter_key
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * The function should send an error when an exporter is missing a friendly name.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_exporter_missing_friendly_name() {
+ $this->_unset_exporter_key( 'exporter_friendly_name' );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Exporter array at index %s does not include a friendly name.',
+ self::$exporter_key
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * The function should send an error when an exporter is missing a callback.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_exporter_missing_callback() {
+ $this->_unset_exporter_key( 'callback' );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Exporter does not include a callback: %s.',
+ self::$exporter_friendly_name
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * The function should send an error when an exporter, at a given index, has an invalid callback.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_exporter_index_invalid_callback() {
+ $this->_set_exporter_callback( false );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Exporter callback is not a valid callback: %s.',
+ self::$exporter_friendly_name
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * When an exporter callback returns a WP_Error, it should be passed as the error.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_exporter_callback_returns_wp_error() {
+ $this->_set_exporter_callback( array( $this, 'callback_return_wp_error' ) );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'passed_message', $this->_last_response_parsed['data'][0]['code'] );
+ $this->assertSame( 'This is a WP_Error message.', $this->_last_response_parsed['data'][0]['message'] );
+ }
+
+ /**
+ * Callback for exporter's response.
+ *
+ * @since 5.2.0
+ *
+ * @param string $email_address The requester's email address.
+ * @param int $page Page number.
+ * @return WP_Error WP_Error instance.
+ */
+ public function callback_return_wp_error( $email_address, $page = 1 ) {
+ return new WP_Error( 'passed_message', 'This is a WP_Error message.' );
+ }
+
+ /**
+ * The function should send an error when an exporter, at a given index, is missing an array response.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_exporter_index_invalid_response() {
+ $this->_set_exporter_callback( '__return_null' );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Expected response as an array from exporter: %s.',
+ self::$exporter_friendly_name
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * The function should send an error when an exporter is missing data in array response.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_exporter_missing_data_response() {
+ $this->_set_exporter_callback( array( $this, 'callback_missing_data_response' ) );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Expected data in response array from exporter: %s.',
+ self::$exporter_friendly_name
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * Callback for exporter's response.
+ *
+ * @since 5.2.0
+ *
+ * @param string $email_address The requester's email address.
+ * @param int $page Page number.
+ *
+ * @return array Export data.
+ */
+ public function callback_missing_data_response( $email_address, $page = 1 ) {
+ $response = $this->callback_custom_personal_data_exporter( $email_address, $page );
+ unset( $response['data'] ); // Missing data part of response.
+
+ return $response;
+ }
+
+ /**
+ * The function should send an error when an exporter is missing 'data' array in array response.
+ *
+ * @since 5.2.0
+ */
+ public function test_function_should_error_when_exporter_missing_data_array_response() {
+ $this->_set_exporter_callback( array( $this, 'callback_missing_data_array_response' ) );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Expected data array in response array from exporter: %s.',
+ self::$exporter_friendly_name
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * Callback for exporter's response.
+ *
+ * @since 5.2.0
+ *
+ * @param string $email_address The requester's email address.
+ * @param int $page Page number.
+ *
+ * @return array Export data.
+ */
+ public function callback_missing_data_array_response( $email_address, $page = 1 ) {
+ $response = $this->callback_custom_personal_data_exporter( $email_address, $page );
+ $response['data'] = false; // Not an array.
+ return $response;
+ }
+
+ /**
+ * The function should send an error when an exporter is missing 'done' in array response.
+ *
+ * @since 5.2.0
+ */
+ public function test_error_when_exporter_missing_done_response() {
+ $this->_set_exporter_callback( array( $this, 'callback_missing_done_response' ) );
+ $this->_make_ajax_call();
+
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame(
+ sprintf(
+ 'Expected done (boolean) in response array from exporter: %s.',
+ self::$exporter_friendly_name
+ ),
+ $this->_last_response_parsed['data']
+ );
+ }
+
+ /**
+ * Remove the response's done flag.
+ *
+ * @since 5.2.0
+ *
+ * @param string $email_address The requester's email address.
+ * @param int $page Page number.
+ *
+ * @return array Export data.
+ */
+ public function callback_missing_done_response( $email_address, $page = 1 ) {
+ $response = $this->callback_custom_personal_data_exporter( $email_address, $page );
+ unset( $response['done'] );
+
+ return $response;
+ }
+
+ /**
+ * The function should successfully send exporter data response when the current user has the required capability.
+ *
+ * @since 5.2.0
+ */
+ public function test_succeeds_when_current_user_has_required_capability() {
+ $this->assertTrue( current_user_can( 'export_others_personal_data' ) );
+
+ $this->_make_ajax_call();
+
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'custom-exporter-item-id', $this->_last_response_parsed['data']['data']['item_id'] );
+ $this->assertSame( 'Email', $this->_last_response_parsed['data']['data']['data'][0]['name'] );
+ $this->assertSame( self::$request_email, $this->_last_response_parsed['data']['data']['data'][0]['value'] );
+ }
+
+ /**
+ * The function should successfully send exporter data response when no items to export.
+ *
+ * @since 5.2.0
+ */
+ public function test_success_when_no_items_to_export() {
+
+ $this->_make_ajax_call( array( 'page' => 2 ) );
+
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertEmpty( $this->_last_response_parsed['data']['data'] );
+ $this->assertTrue( $this->_last_response_parsed['data']['done'] );
+ }
+
+ /**
+ * The function's output should be filterable with the `wp_privacy_personal_data_export_page` filter.
+ *
+ * @since 5.2.0
+ */
+ public function test_output_should_be_filterable() {
+ add_filter( 'wp_privacy_personal_data_export_page', array( $this, 'filter_exporter_data_response' ), 20, 7 );
+ $this->_make_ajax_call();
+
+ $expected_group_label = sprintf(
+ '%s-%s-%s-%s-%s-%s',
+ self::$exporter,
+ self::$page,
+ self::$request_email,
+ self::$request_id,
+ self::$send_as_email,
+ self::$exporter_key
+ );
+
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertSame( $expected_group_label, $this->_last_response_parsed['data']['group_label'] );
+ $this->assertSame( 'filtered_group_id', $this->_last_response_parsed['data']['group_id'] );
+ $this->assertSame( 'filtered_item_id', $this->_last_response_parsed['data']['item_id'] );
+ $this->assertSame( 'filtered_name', $this->_last_response_parsed['data']['data'][0]['name'] );
+ $this->assertSame( 'filtered_value', $this->_last_response_parsed['data']['data'][0]['value'] );
+ }
+
+ /**
+ * Filter exporter's data response.
+ *
+ * @since 5.2.0
+ *
+ * @param array $response The personal data for the given exporter and page.
+ * @param int $exporter_index The index of the exporter that provided this data.
+ * @param string $email_address The email address associated with this personal data.
+ * @param int $page The page for this response.
+ * @param int $request_id The privacy request post ID associated with this request.
+ * @param bool $send_as_email Whether the final results of the export should be emailed to the user.
+ * @param string $exporter_key The key (slug) of the exporter that provided this data.
+ *
+ * @return array The personal data for the given exporter and page.
+ */
+ public function filter_exporter_data_response( $response, $exporter_index, $email_address, $page, $request_id, $send_as_email, $exporter_key ) {
+ $group_label = sprintf(
+ '%s-%s-%s-%s-%s-%s',
+ $exporter_index,
+ $page,
+ $email_address,
+ $request_id,
+ $send_as_email,
+ $exporter_key
+ );
+ $response['group_label'] = $group_label;
+ $response['group_id'] = 'filtered_group_id';
+ $response['item_id'] = 'filtered_item_id';
+ $response['data'][0]['name'] = 'filtered_name';
+ $response['data'][0]['value'] = 'filtered_value';
+
+ return $response;
+ }
+
+ /**
+ * Filter to register a custom personal data exporter.
+ *
+ * @since 5.2.0
+ *
+ * @param array $exporters An array of personal data exporters.
+ *
+ * @return array An array of personal data exporters.
+ */
+ public function filter_register_custom_personal_data_exporter( $exporters ) {
+ $exporters[ self::$exporter_key ] = array(
+ 'exporter_friendly_name' => self::$exporter_friendly_name,
+ 'callback' => array( $this, 'callback_custom_personal_data_exporter' ),
+ );
+ return $exporters;
+ }
+
+ /**
+ * Callback for a custom personal data exporter.
+ *
+ * @since 5.2.0
+ *
+ * @param string $email_address The requester's email address.
+ * @param int $page Page number.
+ *
+ * @return array Export data response.
+ */
+ public function callback_custom_personal_data_exporter( $email_address, $page = 1 ) {
+ $data_to_export = array();
+
+ if ( 1 === $page ) {
+ $data_to_export = array(
+ 'group_id' => self::$exporter_key . '-group-id',
+ 'group_label' => self::$exporter_key . '-group-label',
+ 'item_id' => self::$exporter_key . '-item-id',
+ 'data' => array(
+ array(
+ 'name' => 'Email',
+ 'value' => $email_address,
+ ),
+ ),
+ );
+ }
+
+ return array(
+ 'data' => $data_to_export,
+ 'done' => true,
+ );
+ }
+
+ /**
+ * Helper function for Ajax handler.
+ *
+ * @since 5.2.0
+ *
+ * @param array $args Ajax request arguments.
+ */
+ protected function _make_ajax_call( $args = array() ) {
+ $this->_last_response_parsed = null;
+ $this->_last_response = '';
+
+ $defaults = array(
+ 'action' => self::$action,
+ 'security' => wp_create_nonce( self::$action . '-' . self::$request_id ),
+ 'exporter' => self::$exporter,
+ 'page' => self::$page,
+ 'sendAsEmail' => self::$send_as_email,
+ 'id' => self::$request_id,
+ );
+
+ $_POST = wp_parse_args( $args, $defaults );
+
+ try {
+ $this->_handleAjax( self::$action );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+
+ if ( $this->_last_response ) {
+ $this->_last_response_parsed = json_decode( $this->_last_response, true );
+ }
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpCustomizeManagerphpfromrev54721trunktestsphpunittestsajaxCustomizeManagerphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpCustomizeManager.php (from rev 54721, trunk/tests/phpunit/tests/ajax/CustomizeManager.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpCustomizeManager.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpCustomizeManager.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,769 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Testing Ajax customize manager functionality.
+ *
+ * @package WordPress
+ * @subpackage UnitTests
+ * @since 4.3.0
+ *
+ * @group ajax
+ */
+class Tests_Ajax_wpCustomizeManager extends WP_Ajax_UnitTestCase {
+
+ /**
+ * Instance of WP_Customize_Manager which is reset for each test.
+ *
+ * @var WP_Customize_Manager
+ */
+ public $wp_customize;
+
+ /**
+ * Admin user ID.
+ *
+ * @var int
+ */
+ protected static $admin_user_id;
+
+ /**
+ * Subscriber user ID.
+ *
+ * @var int
+ */
+ protected static $subscriber_user_id;
+
+ /**
+ * Last response parsed.
+ *
+ * @var array|null
+ */
+ protected $_last_response_parsed;
+
+ /**
+ * Set up before class.
+ *
+ * @param WP_UnitTest_Factory $factory Factory.
+ */
+ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
+ self::$subscriber_user_id = $factory->user->create( array( 'role' => 'subscriber' ) );
+ self::$admin_user_id = $factory->user->create( array( 'role' => 'administrator' ) );
+ }
+
+ /**
+ * Set up the test fixture.
+ */
+ public function set_up() {
+ parent::set_up();
+ require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
+ }
+
+ /**
+ * Tear down.
+ */
+ public function tear_down() {
+ $_REQUEST = array();
+ parent::tear_down();
+ }
+
+ /**
+ * Helper to keep it DRY
+ *
+ * @param string $action Action.
+ */
+ protected function make_ajax_call( $action ) {
+ $this->_last_response_parsed = null;
+ $this->_last_response = '';
+ try {
+ $this->_handleAjax( $action );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+ if ( $this->_last_response ) {
+ $this->_last_response_parsed = json_decode( $this->_last_response, true );
+ }
+ }
+
+ /**
+ * Overridden caps for user_has_cap.
+ *
+ * @var array
+ */
+ protected $overridden_caps = array();
+
+ /**
+ * Dynamically filter a user's capabilities.
+ *
+ * @param array $allcaps An array of all the user's capabilities.
+ * @return array All caps.
+ */
+ public function filter_user_has_cap( $allcaps ) {
+ $allcaps = array_merge( $allcaps, $this->overridden_caps );
+ return $allcaps;
+ }
+
+ /**
+ * Test WP_Customize_Manager::save().
+ *
+ * @ticket 30937
+ *
+ * @covers WP_Customize_Manager::save
+ */
+ public function test_save_failures() {
+ global $wp_customize;
+ $wp_customize = new WP_Customize_Manager();
+ $wp_customize->register_controls();
+ add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ) );
+
+ // Unauthenticated.
+ wp_set_current_user( 0 );
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'unauthenticated', $this->_last_response_parsed['data'] );
+
+ // Unauthorized.
+ wp_set_current_user( self::$subscriber_user_id );
+ $nonce = wp_create_nonce( 'save-customize_' . $wp_customize->get_stylesheet() );
+ $_POST['nonce'] = $nonce;
+ $_GET['nonce'] = $nonce;
+ $_REQUEST['nonce'] = $nonce;
+ $exception = null;
+ try {
+ ob_start();
+ $wp_customize->setup_theme();
+ } catch ( WPAjaxDieContinueException $e ) {
+ $exception = $e;
+ }
+ $this->assertNotEmpty( $e );
+ $this->assertSame( '-1', $e->getMessage() );
+
+ // Not called setup_theme.
+ wp_set_current_user( self::$admin_user_id );
+ $nonce = wp_create_nonce( 'save-customize_' . $wp_customize->get_stylesheet() );
+ $_POST['nonce'] = $nonce;
+ $_GET['nonce'] = $nonce;
+ $_REQUEST['nonce'] = $nonce;
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'not_preview', $this->_last_response_parsed['data'] );
+
+ // Bad nonce.
+ $_POST['nonce'] = 'bad';
+ $_GET['nonce'] = 'bad';
+ $_REQUEST['nonce'] = 'bad';
+ $wp_customize->setup_theme();
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'invalid_nonce', $this->_last_response_parsed['data'] );
+
+ // User cannot create.
+ $nonce = wp_create_nonce( 'save-customize_' . $wp_customize->get_stylesheet() );
+ $_POST['nonce'] = $nonce;
+ $_GET['nonce'] = $nonce;
+ $_REQUEST['nonce'] = $nonce;
+ $post_type_obj = get_post_type_object( 'customize_changeset' );
+ $post_type_obj->cap->create_posts = 'create_customize_changesets';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'cannot_create_changeset_post', $this->_last_response_parsed['data'] );
+ $this->overridden_caps[ $post_type_obj->cap->create_posts ] = true;
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $post_type_obj->cap->create_posts = 'customize'; // Restore.
+
+ // Changeset already published.
+ $wp_customize->set_post_value( 'blogname', 'Hello' );
+ $wp_customize->save_changeset_post( array( 'status' => 'publish' ) );
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'changeset_already_published', $this->_last_response_parsed['data']['code'] );
+ wp_update_post(
+ array(
+ 'ID' => $wp_customize->changeset_post_id(),
+ 'post_status' => 'auto-draft',
+ )
+ );
+
+ // User cannot edit.
+ $post_type_obj = get_post_type_object( 'customize_changeset' );
+ $post_type_obj->cap->edit_post = 'edit_customize_changesets';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'cannot_edit_changeset_post', $this->_last_response_parsed['data'] );
+ $this->overridden_caps[ $post_type_obj->cap->edit_post ] = true;
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $post_type_obj->cap->edit_post = 'customize'; // Restore.
+
+ // Bad customize_changeset_data.
+ $_POST['customize_changeset_data'] = '[MALFORMED]';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'invalid_customize_changeset_data', $this->_last_response_parsed['data'] );
+
+ // Bad customize_changeset_status.
+ $_POST['customize_changeset_data'] = '{}';
+ $_POST['customize_changeset_status'] = 'unrecognized';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'bad_customize_changeset_status', $this->_last_response_parsed['data'] );
+
+ // Disallowed publish posts if not allowed.
+ $post_type_obj = get_post_type_object( 'customize_changeset' );
+ $post_type_obj->cap->publish_posts = 'publish_customize_changesets';
+ $_POST['customize_changeset_status'] = 'publish';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'changeset_publish_unauthorized', $this->_last_response_parsed['data'] );
+ $_POST['customize_changeset_status'] = 'future';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'changeset_publish_unauthorized', $this->_last_response_parsed['data'] );
+ $post_type_obj->cap->publish_posts = 'customize'; // Restore.
+
+ // Validate date.
+ $_POST['customize_changeset_status'] = 'draft';
+ $_POST['customize_changeset_date'] = 'BAD DATE';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'bad_customize_changeset_date', $this->_last_response_parsed['data'] );
+ $_POST['customize_changeset_date'] = '2010-01-01 00:00:00';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'not_future_date', $this->_last_response_parsed['data']['code'] );
+ $_POST['customize_changeset_date'] = ( gmdate( 'Y' ) + 1 ) . '-01-01 00:00:00';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $_POST['customize_changeset_status'] = 'future';
+ $_POST['customize_changeset_date'] = '+10 minutes';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'future', get_post_status( $wp_customize->changeset_post_id() ) );
+ wp_update_post(
+ array(
+ 'ID' => $wp_customize->changeset_post_id(),
+ 'post_status' => 'auto-draft',
+ )
+ );
+ }
+
+ /**
+ * Set up valid user state.
+ *
+ * @param string $uuid Changeset UUID.
+ * @return WP_Customize_Manager
+ */
+ protected function set_up_valid_state( $uuid = null ) {
+ global $wp_customize;
+ wp_set_current_user( self::$admin_user_id );
+ $wp_customize = new WP_Customize_Manager(
+ array(
+ 'changeset_uuid' => $uuid,
+ )
+ );
+ $wp_customize->register_controls();
+ $nonce = wp_create_nonce( 'save-customize_' . $wp_customize->get_stylesheet() );
+ $_POST['nonce'] = $nonce;
+ $_GET['nonce'] = $nonce;
+ $_REQUEST['nonce'] = $nonce;
+ $wp_customize->setup_theme();
+ return $wp_customize;
+ }
+
+ /**
+ * Test WP_Customize_Manager::save().
+ *
+ * @ticket 30937
+ *
+ * @covers WP_Customize_Manager::save
+ */
+ public function test_save_success_publish_create() {
+ $wp_customize = $this->set_up_valid_state();
+
+ $_POST['customize_changeset_status'] = 'publish';
+ $_POST['customize_changeset_title'] = 'Success Changeset';
+ $_POST['customize_changeset_data'] = wp_json_encode(
+ array(
+ 'blogname' => array(
+ 'value' => 'Successful Site Title',
+ ),
+ )
+ );
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertIsArray( $this->_last_response_parsed['data'] );
+
+ $this->assertSame( 'publish', $this->_last_response_parsed['data']['changeset_status'] );
+ $this->assertArrayHasKey( 'next_changeset_uuid', $this->_last_response_parsed['data'] );
+ $this->assertTrue( wp_is_uuid( $this->_last_response_parsed['data']['next_changeset_uuid'], 4 ) );
+ $this->assertSame( 'Success Changeset', get_post( $wp_customize->changeset_post_id() )->post_title );
+ $this->assertSame( 'Successful Site Title', get_option( 'blogname' ) );
+ }
+
+ /**
+ * Test WP_Customize_Manager::save().
+ *
+ * @ticket 30937
+ *
+ * @covers WP_Customize_Manager::save
+ */
+ public function test_save_success_publish_edit() {
+ $uuid = wp_generate_uuid4();
+
+ $post_id = self::factory()->post->create(
+ array(
+ 'post_name' => $uuid,
+ 'post_title' => 'Original',
+ 'post_type' => 'customize_changeset',
+ 'post_status' => 'auto-draft',
+ 'post_content' => wp_json_encode(
+ array(
+ 'blogname' => array(
+ 'value' => 'New Site Title',
+ ),
+ )
+ ),
+ )
+ );
+ $wp_customize = $this->set_up_valid_state( $uuid );
+
+ $_POST['customize_changeset_status'] = 'publish';
+ $_POST['customize_changeset_title'] = 'Published';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertIsArray( $this->_last_response_parsed['data'] );
+
+ $this->assertSame( 'publish', $this->_last_response_parsed['data']['changeset_status'] );
+ $this->assertArrayHasKey( 'next_changeset_uuid', $this->_last_response_parsed['data'] );
+ $this->assertTrue( wp_is_uuid( $this->_last_response_parsed['data']['next_changeset_uuid'], 4 ) );
+ $this->assertSame( 'New Site Title', get_option( 'blogname' ) );
+ $this->assertSame( 'Published', get_post( $post_id )->post_title );
+ }
+
+ /**
+ * Test WP_Customize_Manager::save().
+ *
+ * @ticket 38943
+ *
+ * @covers WP_Customize_Manager::save
+ */
+ public function test_success_save_post_date() {
+ $uuid = wp_generate_uuid4();
+ $post_id = self::factory()->post->create(
+ array(
+ 'post_name' => $uuid,
+ 'post_title' => 'Original',
+ 'post_type' => 'customize_changeset',
+ 'post_status' => 'auto-draft',
+ 'post_content' => wp_json_encode(
+ array(
+ 'blogname' => array(
+ 'value' => 'New Site Title',
+ ),
+ )
+ ),
+ )
+ );
+ $wp_customize = $this->set_up_valid_state( $uuid );
+
+ // Success future schedule date.
+ $future_date = ( gmdate( 'Y' ) + 1 ) . '-01-01 00:00:00';
+ $_POST['customize_changeset_status'] = 'future';
+ $_POST['customize_changeset_title'] = 'Future date';
+ $_POST['customize_changeset_date'] = $future_date;
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertArrayHasKey( 'changeset_date', $this->_last_response_parsed['data'] );
+ $changeset_post_schedule = get_post( $post_id );
+ $this->assertSame( $future_date, $changeset_post_schedule->post_date );
+
+ // Success future changeset change to draft keeping existing date.
+ unset( $_POST['customize_changeset_date'] );
+ $_POST['customize_changeset_status'] = 'draft';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertArrayNotHasKey( 'changeset_date', $this->_last_response_parsed['data'] );
+ $changeset_post_draft = get_post( $post_id );
+ $this->assertSame( $future_date, $changeset_post_draft->post_date );
+
+ // Success if date is not passed with schedule changeset and stored changeset have future date.
+ $_POST['customize_changeset_status'] = 'future';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertArrayHasKey( 'changeset_date', $this->_last_response_parsed['data'] );
+ $changeset_post_schedule = get_post( $post_id );
+ $this->assertSame( $future_date, $changeset_post_schedule->post_date );
+ // Success if draft with past date.
+ $now = current_time( 'mysql' );
+ wp_update_post(
+ array(
+ 'ID' => $post_id,
+ 'post_status' => 'draft',
+ 'post_date' => $now,
+ 'post_date_gmt' => get_gmt_from_date( $now ),
+ )
+ );
+
+ // Fail if future request and existing date is past.
+ $_POST['customize_changeset_status'] = 'future';
+ unset( $_POST['customize_changeset_date'] );
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'not_future_date', $this->_last_response_parsed['data']['code'] );
+
+ // Success publish changeset reset date to current.
+ wp_update_post(
+ array(
+ 'ID' => $post_id,
+ 'post_status' => 'future',
+ 'post_date' => $future_date,
+ 'post_date_gmt' => get_gmt_from_date( $future_date ),
+ )
+ );
+ unset( $_POST['customize_changeset_date'] );
+ $_POST['customize_changeset_status'] = 'publish';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertArrayHasKey( 'next_changeset_uuid', $this->_last_response_parsed['data'] );
+ $this->assertTrue( wp_is_uuid( $this->_last_response_parsed['data']['next_changeset_uuid'], 4 ) );
+ $changeset_post_publish = get_post( $post_id );
+ $this->assertNotEquals( $future_date, $changeset_post_publish->post_date );
+
+ // Check response when trying to update an already-published post.
+ $this->assertSame( 'trash', get_post_status( $post_id ) );
+ $_POST['customize_changeset_status'] = 'publish';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'changeset_already_published', $this->_last_response_parsed['data']['code'] );
+ $this->assertArrayHasKey( 'next_changeset_uuid', $this->_last_response_parsed['data'] );
+ $this->assertTrue( wp_is_uuid( $this->_last_response_parsed['data']['next_changeset_uuid'], 4 ) );
+ }
+
+ /**
+ * Test WP_Customize_Manager::save().
+ *
+ * @ticket 39896
+ *
+ * @covers WP_Customize_Manager::save
+ */
+ public function test_save_autosave() {
+ $uuid = wp_generate_uuid4();
+
+ $post_id = self::factory()->post->create(
+ array(
+ 'post_name' => $uuid,
+ 'post_type' => 'customize_changeset',
+ 'post_status' => 'draft',
+ 'post_content' => wp_json_encode(
+ array(
+ 'blogname' => array(
+ 'value' => 'New Site Title',
+ ),
+ )
+ ),
+ )
+ );
+ $this->set_up_valid_state( $uuid );
+
+ $this->assertFalse( wp_get_post_autosave( $post_id ) );
+
+ $_POST['customize_changeset_data'] = wp_json_encode(
+ array(
+ 'blogname' => array(
+ 'value' => 'Autosaved Site Title',
+ ),
+ )
+ );
+
+ $_POST['customize_changeset_autosave'] = 'on';
+ $this->make_ajax_call( 'customize_save' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'draft', $this->_last_response_parsed['data']['changeset_status'] );
+ $autosave_revision = wp_get_post_autosave( $post_id );
+ $this->assertInstanceOf( 'WP_Post', $autosave_revision );
+
+ $this->assertStringContainsString( 'New Site Title', get_post( $post_id )->post_content );
+ $this->assertStringContainsString( 'Autosaved Site Title', $autosave_revision->post_content );
+ }
+
+ /**
+ * Test request for trashing a changeset.
+ *
+ * @ticket 39896
+ *
+ * @covers WP_Customize_Manager::handle_changeset_trash_request
+ */
+ public function test_handle_changeset_trash_request() {
+ $uuid = wp_generate_uuid4();
+ $wp_customize = $this->set_up_valid_state( $uuid );
+
+ $this->make_ajax_call( 'customize_trash' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'invalid_nonce', $this->_last_response_parsed['data']['code'] );
+
+ $nonce = wp_create_nonce( 'trash_customize_changeset' );
+ $_POST['nonce'] = $nonce;
+ $_GET['nonce'] = $nonce;
+ $_REQUEST['nonce'] = $nonce;
+ $this->make_ajax_call( 'customize_trash' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'non_existent_changeset', $this->_last_response_parsed['data']['code'] );
+
+ $wp_customize->register_controls(); // And settings too.
+ $wp_customize->set_post_value( 'blogname', 'HELLO' );
+ $wp_customize->save_changeset_post(
+ array(
+ 'status' => 'save',
+ )
+ );
+
+ add_filter( 'map_meta_cap', array( $this, 'return_do_not_allow' ) );
+ $this->make_ajax_call( 'customize_trash' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'changeset_trash_unauthorized', $this->_last_response_parsed['data']['code'] );
+ remove_filter( 'map_meta_cap', array( $this, 'return_do_not_allow' ) );
+
+ $lock_user_id = static::factory()->user->create( array( 'role' => 'administrator' ) );
+ $previous_user = get_current_user_id();
+ wp_set_current_user( $lock_user_id );
+ $wp_customize->set_changeset_lock( $wp_customize->changeset_post_id() );
+ wp_set_current_user( $previous_user );
+ $this->make_ajax_call( 'customize_trash' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'changeset_locked', $this->_last_response_parsed['data']['code'] );
+ delete_post_meta( $wp_customize->changeset_post_id(), '_edit_lock' );
+
+ wp_update_post(
+ array(
+ 'ID' => $wp_customize->changeset_post_id(),
+ 'post_status' => 'trash',
+ )
+ );
+ $this->make_ajax_call( 'customize_trash' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'changeset_already_trashed', $this->_last_response_parsed['data']['code'] );
+
+ wp_update_post(
+ array(
+ 'ID' => $wp_customize->changeset_post_id(),
+ 'post_status' => 'draft',
+ )
+ );
+
+ $wp_trash_post_count = did_action( 'wp_trash_post' );
+ add_filter( 'pre_trash_post', '__return_false' );
+ $this->make_ajax_call( 'customize_trash' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'changeset_trash_failure', $this->_last_response_parsed['data']['code'] );
+ remove_filter( 'pre_trash_post', '__return_false' );
+ $this->assertSame( $wp_trash_post_count, did_action( 'wp_trash_post' ) );
+
+ $wp_trash_post_count = did_action( 'wp_trash_post' );
+ $this->assertSame( 'draft', get_post_status( $wp_customize->changeset_post_id() ) );
+ $this->make_ajax_call( 'customize_trash' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'trash', get_post_status( $wp_customize->changeset_post_id() ) );
+ $this->assertSame( $wp_trash_post_count + 1, did_action( 'wp_trash_post' ) );
+ }
+
+ /**
+ * Return caps array containing 'do_not_allow'.
+ *
+ * @return array Caps.
+ */
+ public function return_do_not_allow() {
+ return array( 'do_not_allow' );
+ }
+
+ /**
+ * Test request for dismissing autosave changesets.
+ *
+ * @ticket 39896
+ * @covers WP_Customize_Manager::handle_dismiss_autosave_or_lock_request
+ * @covers WP_Customize_Manager::dismiss_user_auto_draft_changesets
+ */
+ public function test_handle_dismiss_autosave_or_lock_request() {
+ $uuid = wp_generate_uuid4();
+ $wp_customize = $this->set_up_valid_state( $uuid );
+ $valid_user_id = get_current_user_id();
+
+ // Temporarily remove user to test requirement that user is logged in. See #42450.
+ wp_set_current_user( 0 );
+ $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'unauthenticated', $this->_last_response_parsed['data'] );
+ wp_set_current_user( $valid_user_id );
+
+ $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'invalid_nonce', $this->_last_response_parsed['data'] );
+
+ $nonce = wp_create_nonce( 'customize_dismiss_autosave_or_lock' );
+ $_POST['nonce'] = $nonce;
+ $_GET['nonce'] = $nonce;
+ $_REQUEST['nonce'] = $nonce;
+
+ $_POST['dismiss_lock'] = true;
+ $_GET['dismiss_lock'] = true;
+ $_REQUEST['dismiss_lock'] = true;
+ $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'no_changeset_to_dismiss_lock', $this->_last_response_parsed['data'] );
+
+ $_POST['dismiss_autosave'] = true;
+ $_GET['dismiss_autosave'] = true;
+ $_REQUEST['dismiss_autosave'] = true;
+ $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'no_auto_draft_to_delete', $this->_last_response_parsed['data'] );
+
+ $other_user_id = self::factory()->user->create();
+
+ // Create auto-drafts.
+ $user_auto_draft_ids = array();
+ for ( $i = 0; $i < 3; $i++ ) {
+ $user_auto_draft_ids[] = self::factory()->post->create(
+ array(
+ 'post_name' => wp_generate_uuid4(),
+ 'post_type' => 'customize_changeset',
+ 'post_status' => 'auto-draft',
+ 'post_author' => self::$admin_user_id,
+ 'post_content' => wp_json_encode( array() ),
+ )
+ );
+ }
+ $other_user_auto_draft_ids = array();
+ for ( $i = 0; $i < 3; $i++ ) {
+ $other_user_auto_draft_ids[] = self::factory()->post->create(
+ array(
+ 'post_name' => wp_generate_uuid4(),
+ 'post_type' => 'customize_changeset',
+ 'post_status' => 'auto-draft',
+ 'post_author' => $other_user_id,
+ 'post_content' => wp_json_encode( array() ),
+ )
+ );
+ }
+ foreach ( array_merge( $user_auto_draft_ids, $other_user_auto_draft_ids ) as $post_id ) {
+ $this->assertFalse( (bool) get_post_meta( $post_id, '_customize_restore_dismissed', true ) );
+ }
+ $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'auto_draft_dismissed', $this->_last_response_parsed['data'] );
+ foreach ( $user_auto_draft_ids as $post_id ) {
+ $this->assertSame( 'auto-draft', get_post_status( $post_id ) );
+ $this->assertTrue( (bool) get_post_meta( $post_id, '_customize_restore_dismissed', true ) );
+ }
+ foreach ( $other_user_auto_draft_ids as $post_id ) {
+ $this->assertSame( 'auto-draft', get_post_status( $post_id ) );
+ $this->assertFalse( (bool) get_post_meta( $post_id, '_customize_restore_dismissed', true ) );
+ }
+
+ // Subsequent test results in none dismissed.
+ $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'no_auto_draft_to_delete', $this->_last_response_parsed['data'] );
+
+ // Save a changeset as a draft.
+ $r = $wp_customize->save_changeset_post(
+ array(
+ 'data' => array(
+ 'blogname' => array(
+ 'value' => 'Foo',
+ ),
+ ),
+ 'status' => 'draft',
+ )
+ );
+
+ $_POST['dismiss_autosave'] = false;
+ $_GET['dismiss_autosave'] = false;
+ $_REQUEST['dismiss_autosave'] = false;
+ $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'changeset_lock_dismissed', $this->_last_response_parsed['data'] );
+
+ $_POST['dismiss_autosave'] = true;
+ $_GET['dismiss_autosave'] = true;
+ $_REQUEST['dismiss_autosave'] = true;
+ $this->assertNotWPError( $r );
+ $this->assertFalse( wp_get_post_autosave( $wp_customize->changeset_post_id() ) );
+ $this->assertStringContainsString( 'Foo', get_post( $wp_customize->changeset_post_id() )->post_content );
+
+ // Since no autosave yet, confirm no action.
+ $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'no_autosave_revision_to_delete', $this->_last_response_parsed['data'] );
+
+ // Add the autosave revision.
+ $r = $wp_customize->save_changeset_post(
+ array(
+ 'data' => array(
+ 'blogname' => array(
+ 'value' => 'Bar',
+ ),
+ ),
+ 'autosave' => true,
+ )
+ );
+ $this->assertNotWPError( $r );
+ $autosave_revision = wp_get_post_autosave( $wp_customize->changeset_post_id() );
+ $this->assertInstanceOf( 'WP_Post', $autosave_revision );
+ $this->assertStringContainsString( 'Foo', get_post( $wp_customize->changeset_post_id() )->post_content );
+ $this->assertStringContainsString( 'Bar', $autosave_revision->post_content );
+
+ // Confirm autosave gets deleted.
+ $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
+ $this->assertTrue( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'autosave_revision_deleted', $this->_last_response_parsed['data'] );
+ $this->assertFalse( wp_get_post_autosave( $wp_customize->changeset_post_id() ) );
+
+ // Since no autosave yet, confirm no action.
+ $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
+ $this->assertFalse( $this->_last_response_parsed['success'] );
+ $this->assertSame( 'no_autosave_revision_to_delete', $this->_last_response_parsed['data'] );
+ }
+
+ /**
+ * Test request for retrieving installed themes.
+ *
+ * @ticket 54549
+ * @covers WP_Customize_Manager::handle_load_themes_request
+ */
+ public function test_wp_ajax_customize_load_themes_action() {
+ $arguments = array(
+ 'changeset_uuid' => false,
+ 'settings_previewed' => true,
+ 'branching' => false,
+ );
+ new WP_Customize_Manager( $arguments );
+ wp_set_current_user( self::$admin_user_id );
+ $nonce = wp_create_nonce( 'switch_themes' );
+ $_POST['nonce'] = $nonce;
+ $_GET['nonce'] = $nonce;
+ $_REQUEST['nonce'] = $nonce;
+ $_POST['theme_action'] = 'installed';
+ $this->make_ajax_call( 'customize_load_themes' );
+ $response = $this->_last_response_parsed;
+ $this->assertIsArray( $response, 'Response is not an array' );
+
+ $this->assertArrayHasKey( 'success', $response, 'Response must have a "success" key' );
+ $this->assertTrue( $response['success'], 'Response was not "success"' );
+
+ $this->assertArrayHasKey( 'data', $response, 'Response must have a "data" key' );
+ $this->assertIsArray( $response['data'], 'The response "data" is not an array' );
+ $this->assertArrayHasKey( 'themes', $response['data'], 'The response data must have a "themes" key' );
+ $this->assertIsArray( $response['data']['themes'], 'Themes data is not an array' );
+ $this->assertNotEmpty( $response['data']['themes'], 'Themes data must not be empty' );
+
+ foreach ( $response['data']['themes'] as $theme ) {
+ $this->assertIsArray( $theme, 'Theme is not an array' );
+ $this->assertNotEmpty( $theme, 'Theme data must not be empty' );
+ $this->assertArrayHasKey( 'id', $theme, 'Theme data must have an "id" key' );
+ $this->assertNotEmpty( $theme['id'], 'Theme id cannot be empty' );
+
+ $this->assertArrayHasKey( 'name', $theme, 'Theme data must have a "name" key' );
+ $this->assertNotEmpty( $theme['name'], 'Theme name cannot be empty' );
+
+ $this->assertArrayHasKey( 'blockTheme', $theme, 'Themes data must include information about blocks support' );
+ }
+ }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestsajaxwpCustomizeNavMenusphpfromrev54721trunktestsphpunittestsajaxCustomizeMenusphp"></a>
<div class="copfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Copied: trunk/tests/phpunit/tests/ajax/wpCustomizeNavMenus.php (from rev 54721, trunk/tests/phpunit/tests/ajax/CustomizeMenus.php)</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/ajax/wpCustomizeNavMenus.php (rev 0)
+++ trunk/tests/phpunit/tests/ajax/wpCustomizeNavMenus.php 2022-10-30 01:05:06 UTC (rev 54722)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,800 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Testing Ajax customize menus functionality.
+ *
+ * @package WordPress
+ * @subpackage UnitTests
+ * @since 4.3.0
+ *
+ * @group ajax
+ */
+class Tests_Ajax_wpCustomizeNavMenus extends WP_Ajax_UnitTestCase {
+
+ /**
+ * Instance of WP_Customize_Manager which is reset for each test.
+ *
+ * @var WP_Customize_Manager
+ */
+ public $wp_customize;
+
+ /**
+ * Page IDs.
+ *
+ * @var int[]
+ */
+ public static $pages;
+
+ /**
+ * Post IDs.
+ *
+ * @var int[]
+ */
+ public static $posts;
+
+ /**
+ * Term IDs.
+ *
+ * @var int[]
+ */
+ public static $terms;
+
+ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
+ // Make some post objects.
+ self::$posts = $factory->post->create_many( 5 );
+ self::$pages = $factory->post->create_many( 5, array( 'post_type' => 'page' ) );
+
+ // Some terms too.
+ self::$terms = $factory->term->create_many( 5 );
+ }
+
+ /**
+ * Set up the test fixture.
+ */
+ public function set_up() {
+ parent::set_up();
+ require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
+ wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
+ global $wp_customize;
+ $this->wp_customize = new WP_Customize_Manager();
+ $wp_customize = $this->wp_customize;
+ }
+
+ /**
+ * Helper to keep it DRY
+ *
+ * @param string $action Action.
+ */
+ protected function make_ajax_call( $action ) {
+ // Make the request.
+ try {
+ $this->_handleAjax( $action );
+ } catch ( WPAjaxDieContinueException $e ) {
+ unset( $e );
+ }
+ }
+
+ /**
+ * Testing capabilities check for ajax_load_available_items method
+ *
+ * @dataProvider data_ajax_load_available_items_cap_check
+ *
+ * @covers WP_Customize_Nav_Menus::ajax_load_available_items
+ *
+ * @param string $role The role we're checking caps against.
+ * @param array $expected_results Expected results.
+ */
+ public function test_ajax_load_available_items_cap_check( $role, $expected_results ) {
+
+ if ( 'administrator' !== $role ) {
+ // If we're not an admin, we should get a wp_die( -1 ).
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ }
+
+ wp_set_current_user( self::factory()->user->create( array( 'role' => $role ) ) );
+
+ $_POST = array(
+ 'action' => 'load-available-menu-items-customizer',
+ 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
+ );
+
+ $this->make_ajax_call( 'load-available-menu-items-customizer' );
+
+ // If we are an admin, we should get a proper response.
+ if ( 'administrator' === $role ) {
+ // Get the results.
+ $response = json_decode( $this->_last_response, true );
+
+ $this->assertSame( $expected_results, $response );
+ }
+
+ }
+
+ /**
+ * Data provider for test_ajax_load_available_items_cap_check().
+ *
+ * Provides various post_args to induce error messages in the that can be
+ * compared to the expected_results.
+ *
+ * @since 4.3.0
+ *
+ * @return array {
+ * @type array {
+ * @string string $role The role that will test caps for.
+ * @array array $expected_results The expected results from the Ajax call.
+ * }
+ * }
+ */
+ public function data_ajax_load_available_items_cap_check() {
+ return array(
+ array(
+ 'subscriber',
+ array(),
+ ),
+ array(
+ 'contributor',
+ array(),
+ ),
+ array(
+ 'author',
+ array(),
+ ),
+ array(
+ 'editor',
+ array(),
+ ),
+ array(
+ 'administrator',
+ array(
+ 'success' => false,
+ 'data' => 'nav_menus_missing_type_or_object_parameter',
+ ),
+ ),
+ );
+ }
+
+ /**
+ * Testing the error messaging for ajax_load_available_items
+ *
+ * @dataProvider data_ajax_load_available_items_error_messages
+ *
+ * @covers WP_Customize_Nav_Menus::ajax_load_available_items
+ *
+ * @param array $post_args POST args.
+ * @param mixed $expected_results Expected results.
+ */
+ public function test_ajax_load_available_items_error_messages( $post_args, $expected_results ) {
+
+ $_POST = array_merge(
+ array(
+ 'action' => 'load-available-menu-items-customizer',
+ 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
+ ),
+ $post_args
+ );
+
+ // Make the request.
+ $this->make_ajax_call( 'load-available-menu-items-customizer' );
+
+ // Get the results.
+ $response = json_decode( $this->_last_response, true );
+
+ $this->assertSame( $expected_results, $response );
+ }
+
+ /**
+ * Data provider for test_ajax_load_available_items_error_message().
+ *
+ * Provides various post_args to induce error messages in the that can be
+ * compared to the expected_results.
+ *
+ * @since 4.3.0
+ *
+ * @return array {
+ * @type array {
+ * @array array $post_args The arguments that will merged with the $_POST array.
+ * @array array $expected_results The expected results from the Ajax call.
+ * }
+ * }
+ */
+ public function data_ajax_load_available_items_error_messages() {
+ return array(
+ // Testing empty obj_type and type.
+ array(
+ array(
+ 'type' => '',
+ 'object' => '',
+ ),
+ array(
+ 'success' => false,
+ 'data' => 'nav_menus_missing_type_or_object_parameter',
+ ),
+ ),
+ // Testing empty obj_type.
+ array(
+ array(
+ 'type' => 'post_type',
+ 'object' => '',
+ ),
+ array(
+ 'success' => false,
+ 'data' => 'nav_menus_missing_type_or_object_parameter',
+ ),
+ ),
+ // Testing empty type.
+ array(
+ array(
+ 'type' => '',
+ 'object' => 'post',
+ ),
+ array(
+ 'success' => false,
+ 'data' => 'nav_menus_missing_type_or_object_parameter',
+ ),
+ ),
+ // Testing empty type of a bulk request.
+ array(
+ array(
+ 'item_types' => array(
+ array(
+ 'type' => 'post_type',
+ 'object' => 'post',
+ ),
+ array(
+ 'type' => 'post_type',
+ 'object' => '',
+ ),
+ ),
+ ),
+ array(
+ 'success' => false,
+ 'data' => 'nav_menus_missing_type_or_object_parameter',
+ ),
+ ),
+ // Testing incorrect type option.
+ array(
+ array(
+ 'type' => 'post_type',
+ 'object' => 'invalid',
+ ),
+ array(
+ 'success' => false,
+ 'data' => 'nav_menus_invalid_post_type',
+ ),
+ ),
+ );
+ }
+
+ /**
+ * Testing the success status.
+ *
+ * @dataProvider data_ajax_load_available_items_success_status
+ *
+ * @covers WP_Customize_Nav_Menus::ajax_load_available_items
+ *
+ * @param array $post_args POST args.
+ * @param array $success_status Success status.
+ */
+ public function test_ajax_load_available_items_success_status( $post_args, $success_status ) {
+
+ $_POST = array_merge(
+ array(
+ 'action' => 'load-available-menu-items-customizer',
+ 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
+ ),
+ $post_args
+ );
+
+ // Make the request.
+ $this->make_ajax_call( 'load-available-menu-items-customizer' );
+
+ // Get the results.
+ $response = json_decode( $this->_last_response, true );
+ $this->assertSame( $success_status, $response['success'] );
+
+ }
+
+ /**
+ * Data provider for test_ajax_load_available_items_success_status().
+ *
+ * Provides various post_args to retrieve results and compare against
+ * the success status.
+ *
+ * @since 4.3.0
+ *
+ * @return array {
+ * @type array {
+ * @type array $post_args The arguments that will merged with the $_POST array.
+ * @type bool $success_status The expected success status.
+ * }
+ * }
+ */
+ public function data_ajax_load_available_items_success_status() {
+ return array(
+ array(
+ array(
+ 'type' => 'post_type',
+ 'object' => 'post',
+ ),
+ true,
+ ),
+ array(
+ array(
+ 'type' => 'post_type',
+ 'object' => 'page',
+ ),
+ true,
+ ),
+ array(
+ array(
+ 'type' => 'post_type',
+ 'object' => 'custom',
+ ),
+ false,
+ ),
+ array(
+ array(
+ 'type' => 'taxonomy',
+ 'object' => 'post_tag',
+ ),
+ true,
+ ),
+ // Testing a bulk request.
+ array(
+ array(
+ 'item_types' => array(
+ array(
+ 'type' => 'post_type',
+ 'object' => 'post',
+ ),
+ array(
+ 'type' => 'post_type',
+ 'object' => 'page',
+ ),
+ ),
+ ),
+ true,
+ ),
+ );
+ }
+
+ /**
+ * Testing the array structure for a single item
+ *
+ * @dataProvider data_ajax_load_available_items_structure
+ *
+ * @covers WP_Customize_Nav_Menus::ajax_load_available_items
+ *
+ * @param array $post_args POST args.
+ */
+ public function test2_ajax_load_available_items_structure( $post_args ) {
+ do_action( 'customize_register', $this->wp_customize );
+
+ $expected_keys = array(
+ 'id',
+ 'title',
+ 'type',
+ 'type_label',
+ 'object',
+ 'object_id',
+ 'url',
+ );
+
+ $auto_draft_post = $this->wp_customize->nav_menus->insert_auto_draft_post(
+ array(
+ 'post_title' => 'Test Auto Draft',
+ 'post_type' => 'post',
+ )
+ );
+ $this->wp_customize->set_post_value( 'nav_menus_created_posts', array( $auto_draft_post->ID ) );
+ $this->wp_customize->get_setting( 'nav_menus_created_posts' )->preview();
+
+ $_POST = array_merge(
+ array(
+ 'action' => 'load-available-menu-items-customizer',
+ 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
+ ),
+ $post_args
+ );
+
+ // Make the request.
+ $this->make_ajax_call( 'load-available-menu-items-customizer' );
+
+ // Get the results.
+ $response = json_decode( $this->_last_response, true );
+
+ $this->assertNotEmpty( current( $response['data']['items'] ) );
+
+ // Get the second index to avoid the home page edge case.
+ $first_prop = current( $response['data']['items'] );
+ $test_item = $first_prop[1];
+
+ foreach ( $expected_keys as $key ) {
+ $this->assertArrayHasKey( $key, $test_item );
+ $this->assertNotEmpty( $test_item[ $key ] );
+ }
+
+ // Special test for the home page.
+ if ( 'page' === $test_item['object'] ) {
+ $first_prop = current( $response['data']['items'] );
+ $home = $first_prop[0];
+ foreach ( $expected_keys as $key ) {
+ if ( 'object_id' !== $key ) {
+ $this->assertArrayHasKey( $key, $home );
+ if ( 'object' !== $key ) {
+ $this->assertNotEmpty( $home[ $key ] );
+ }
+ }
+ }
+ } elseif ( 'post' === $test_item['object'] ) {
+ $item_ids = wp_list_pluck( $response['data']['items']['post_type:post'], 'id' );
+ $this->assertContains( 'post-' . $auto_draft_post->ID, $item_ids );
+ }
+ }
+
+ /**
+ * Data provider for test_ajax_load_available_items_structure().
+ *
+ * Provides various post_args to return a list of items to test the array structure of.
+ *
+ * @since 4.3.0
+ *
+ * @return array {
+ * @type array {
+ * @type array $post_args The arguments that will merged with the $_POST array.
+ * }
+ * }
+ */
+ public function data_ajax_load_available_items_structure() {
+ return array(
+ array(
+ array(
+ 'type' => 'post_type',
+ 'object' => 'post',
+ ),
+ ),
+ array(
+ array(
+ 'type' => 'post_type',
+ 'object' => 'page',
+ ),
+ ),
+ array(
+ array(
+ 'type' => 'taxonomy',
+ 'object' => 'post_tag',
+ ),
+ ),
+ );
+ }
+
+ /**
+ * Testing the error messages for ajax_search_available_items
+ *
+ * @dataProvider data_ajax_search_available_items_caps_check
+ *
+ * @covers WP_Customize_Nav_Menus::ajax_search_available_items
+ * @covers WP_Customize_Nav_Menus::search_available_items_query
+ *
+ * @param string $role Role.
+ * @param array $expected_results Expected results.
+ */
+ public function test_ajax_search_available_items_caps_check( $role, $expected_results ) {
+
+ if ( 'administrator' !== $role ) {
+ // If we're not an admin, we should get a wp_die( -1 ).
+ $this->expectException( 'WPAjaxDieStopException' );
+ $this->expectExceptionMessage( '-1' );
+ }
+
+ wp_set_current_user( self::factory()->user->create( array( 'role' => $role ) ) );
+
+ $_POST = array(
+ 'action' => 'search-available-menu-items-customizer',
+ 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
+ );
+
+ $this->make_ajax_call( 'search-available-menu-items-customizer' );
+
+ // If we are an admin, we should get a proper response.
+ if ( 'administrator' === $role ) {
+ // Get the results.
+ $response = json_decode( $this->_last_response, true );
+
+ $this->assertSame( $expected_results, $response );
+ }
+ }
+
+ /**
+ * Data provider for test_ajax_search_available_items_caps_check().
+ *
+ * Provides various post_args to induce error messages in the that can be
+ * compared to the expected_results.
+ *
+ * @since 4.3.0
+ *
+ * @todo Make this more DRY
+ *
+ * @return array {
+ * @type array {
+ * @string string $role The role that will test caps for.
+ * @array array $expected_results The expected results from the Ajax call.
+ * }
+ * }
+ */
+ public function data_ajax_search_available_items_caps_check() {
+ return array(
+ array(
+ 'subscriber',
+ array(),
+ ),
+ array(
+ 'contributor',
+ array(),
+ ),
+ array(
+ 'author',
+ array(),
+ ),
+ array(
+ 'editor',
+ array(),
+ ),
+ array(
+ 'administrator',
+ array(
+ 'success' => false,
+ 'data' => 'nav_menus_missing_search_parameter',
+ ),
+ ),
+ );
+ }
+
+ /**
+ * Testing the results of various searches
+ *
+ * @dataProvider data_ajax_search_available_items_results
+ *
+ * @covers WP_Customize_Nav_Menus::ajax_search_available_items
+ * @covers WP_Customize_Nav_Menus::search_available_items_query
+ *
+ * @param array $post_args POST args.
+ * @param array $expected_results Expected results.
+ */
+ public function test_ajax_search_available_items_results( $post_args, $expected_results ) {
+ do_action( 'customize_register', $this->wp_customize );
+
+ self::factory()->post->create_many( 5, array( 'post_title' => 'Test Post' ) );
+ $included_auto_draft_post = $this->wp_customize->nav_menus->insert_auto_draft_post(
+ array(
+ 'post_title' => 'Test Included Auto Draft',
+ 'post_type' => 'post',
+ )
+ );
+ $excluded_auto_draft_post = $this->wp_customize->nav_menus->insert_auto_draft_post(
+ array(
+ 'post_title' => 'Excluded Auto Draft',
+ 'post_type' => 'post',
+ )
+ );
+ $this->wp_customize->set_post_value( 'nav_menus_created_posts', array( $included_auto_draft_post->ID, $excluded_auto_draft_post->ID ) );
+ $this->wp_customize->get_setting( 'nav_menus_created_posts' )->preview();
+
+ $_POST = array_merge(
+ array(
+ 'action' => 'search-available-menu-items-customizer',
+ 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
+ ),
+ $post_args
+ );
+
+ $this->make_ajax_call( 'search-available-menu-items-customizer' );
+
+ $response = json_decode( $this->_last_response, true );
+
+ if ( isset( $post_args['search'] ) && 'test' === $post_args['search'] ) {
+ $this->assertTrue( $response['success'] );
+ $this->assertCount( 6, $response['data']['items'] );
+ $item_ids = wp_list_pluck( $response['data']['items'], 'id' );
+ $this->assertContains( 'post-' . $included_auto_draft_post->ID, $item_ids );
+ $this->assertNotContains( 'post-' . $excluded_auto_draft_post->ID, $item_ids );
+ } else {
+ $this->assertSame( $expected_results, $response );
+ }
+ }
+
+ /**
+ * Data provider for test_ajax_search_available_items_results().
+ *
+ * Provides various post_args to test the results.
+ *
+ * @since 4.3.0
+ *
+ * @return array {
+ * @type array {
+ * @string string $post_args The args that will be passed to Ajax.
+ * @array array $expected_results The expected results from the Ajax call.
+ * }
+ * }
+ */
+ public function data_ajax_search_available_items_results() {
+ return array(
+ array(
+ array(),
+ array(
+ 'success' => false,
+ 'data' => 'nav_menus_missing_search_parameter',
+ ),
+ ),
+ array(
+ array(
+ 'search' => 'all_the_things',
+ ),
+ array(
+ 'success' => false,
+ 'data' => array(
+ 'message' => 'No results found.',
+ ),
+ ),
+ ),
+ array(
+ array(
+ 'search' => 'test',
+ ),
+ array(
+ 'success' => true,
+ array(),
+ ),
+ ),
+ );
+ }
+
+ /**
+ * Testing successful ajax_insert_auto_draft_post() call.
+ *
+ * @covers WP_Customize_Nav_Menus::ajax_insert_auto_draft_post
+ * @covers WP_Customize_Nav_Menus::insert_auto_draft_post
+ */
+ public function test_ajax_insert_auto_draft_post_success() {
+ $_POST = wp_slash(
+ array(
+ 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
+ 'params' => array(
+ 'post_type' => 'post',
+ 'post_title' => 'Hello World',
+ ),
+ )
+ );
+ $this->_last_response = '';
+ $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
+ $response = json_decode( $this->_last_response, true );
+
+ $this->assertTrue( $response['success'] );
+ $this->assertArrayHasKey( 'post_id', $response['data'] );
+ $this->assertArrayHasKey( 'url', $response['data'] );
+ $post = get_post( $response['data']['post_id'] );
+ $this->assertSame( 'Hello World', $post->post_title );
+ $this->assertSame( 'post', $post->post_type );
+ $this->assertSame( '', $post->post_name );
+ $this->assertSame( 'hello-world', get_post_meta( $post->ID, '_customize_draft_post_name', true ) );
+ $this->assertSame( $this->wp_customize->changeset_uuid(), get_post_meta( $post->ID, '_customize_changeset_uuid', true ) );
+ }
+
+ /**
+ * Testing unsuccessful ajax_insert_auto_draft_post() call.
+ *
+ * @covers WP_Customize_Nav_Menus::ajax_insert_auto_draft_post
+ */
+ public function test_ajax_insert_auto_draft_failures() {
+ // No nonce.
+ $_POST = array();
+ $this->_last_response = '';
+ $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
+ $response = json_decode( $this->_last_response, true );
+ $this->assertFalse( $response['success'] );
+ $this->assertSame( 'bad_nonce', $response['data'] );
+
+ // Bad nonce.
+ $_POST = wp_slash(
+ array(
+ 'customize-menus-nonce' => 'bad',
+ )
+ );
+ $this->_last_response = '';
+ $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
+ $response = json_decode( $this->_last_response, true );
+ $this->assertFalse( $response['success'] );
+ $this->assertSame( 'bad_nonce', $response['data'] );
+
+ // Bad nonce.
+ wp_set_current_user( self::factory()->user->create( array( 'role' => 'subscriber' ) ) );
+ $_POST = wp_slash(
+ array(
+ 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
+ )
+ );
+ $this->_last_response = '';
+ $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
+ $response = json_decode( $this->_last_response, true );
+ $this->assertFalse( $response['success'] );
+ $this->assertSame( 'customize_not_allowed', $response['data'] );
+
+ // Missing params.
+ wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
+ $_POST = wp_slash(
+ array(
+ 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
+ )
+ );
+ $this->_last_response = '';
+ $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
+ $response = json_decode( $this->_last_response, true );
+ $this->assertFalse( $response['success'] );
+ $this->assertSame( 'missing_params', $response['data'] );
+
+ // insufficient_post_permissions.
+ register_post_type( 'privilege', array( 'capability_type' => 'privilege' ) );
+ $_POST = wp_slash(
+ array(
+ 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
+ 'params' => array(
+ 'post_type' => 'privilege',
+ ),
+ )
+ );
+ $this->_last_response = '';
+ $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
+ $response = json_decode( $this->_last_response, true );
+ $this->assertFalse( $response['success'] );
+ $this->assertSame( 'insufficient_post_permissions', $response['data'] );
+
+ // insufficient_post_permissions.
+ $_POST = wp_slash(
+ array(
+ 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
+ 'params' => array(
+ 'post_type' => 'non-existent',
+ ),
+ )
+ );
+ $this->_last_response = '';
+ $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
+ $response = json_decode( $this->_last_response, true );
+ $this->assertFalse( $response['success'] );
+ $this->assertSame( 'missing_post_type_param', $response['data'] );
+
+ // missing_post_title.
+ $_POST = wp_slash(
+ array(
+ 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
+ 'params' => array(
+ 'post_type' => 'post',
+ 'post_title' => ' ',
+ ),
+ )
+ );
+ $this->_last_response = '';
+ $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
+ $response = json_decode( $this->_last_response, true );
+ $this->assertFalse( $response['success'] );
+ $this->assertSame( 'missing_post_title', $response['data'] );
+
+ // illegal_params.
+ $_POST = wp_slash(
+ array(
+ 'customize-menus-nonce' => wp_create_nonce( 'customize-menus' ),
+ 'params' => array(
+ 'post_type' => 'post',
+ 'post_title' => 'OK',
+ 'post_name' => 'bad',
+ 'post_content' => 'bad',
+ ),
+ )
+ );
+ $this->_last_response = '';
+ $this->make_ajax_call( 'customize-nav-menus-insert-auto-draft' );
+ $response = json_decode( $this->_last_response, true );
+ $this->assertFalse( $response['success'] );
+ $this->assertSame( 'illegal_params', $response['data'] );
+ }
+}
</ins></span></pre>
</div>
</div>
</body>
</html>