diff --git a/composer.lock b/composer.lock index 5d894b2b..0ee8f26a 100644 --- a/composer.lock +++ b/composer.lock @@ -2452,16 +2452,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.16.0", + "version": "v4.17.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "19526a33fb561ef417e822e85f08a00db4059c17" + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", - "reference": "19526a33fb561ef417e822e85f08a00db4059c17", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "shasum": "" }, "require": { @@ -2502,9 +2502,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" }, - "time": "2023-06-25T14:52:30+00:00" + "time": "2023-08-13T19:53:39+00:00" }, { "name": "phar-io/manifest", @@ -2619,21 +2619,21 @@ }, { "name": "php-stubs/wordpress-stubs", - "version": "v6.2.1", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/php-stubs/wordpress-stubs.git", - "reference": "0009429e639b748eef1c955200ea0d4e5ad5627d" + "reference": "adda7609e71d5f4dc7b87c74f8ec9e3437d2e92c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/0009429e639b748eef1c955200ea0d4e5ad5627d", - "reference": "0009429e639b748eef1c955200ea0d4e5ad5627d", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/adda7609e71d5f4dc7b87c74f8ec9e3437d2e92c", + "reference": "adda7609e71d5f4dc7b87c74f8ec9e3437d2e92c", "shasum": "" }, "require-dev": { - "nikic/php-parser": "< 4.12.0", - "php": "~7.3 || ~8.0", + "nikic/php-parser": "^4.13", + "php": "^7.4 || ~8.0.0", "php-stubs/generator": "^0.8.3", "phpdocumentor/reflection-docblock": "^5.3", "phpstan/phpstan": "^1.10.12", @@ -2641,7 +2641,6 @@ }, "suggest": { "paragonie/sodium_compat": "Pure PHP implementation of libsodium", - "symfony/polyfill-php73": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan" }, "type": "library", @@ -2658,9 +2657,9 @@ ], "support": { "issues": "https://github.com/php-stubs/wordpress-stubs/issues", - "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.2.1" + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.3.0" }, - "time": "2023-05-18T04:35:23+00:00" + "time": "2023-08-10T16:34:11+00:00" }, { "name": "php-webdriver/webdriver", @@ -2948,16 +2947,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.28", + "version": "1.10.29", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "e4545b55904ebef470423d3ddddb74fa7325497a" + "reference": "ee5d8f2d3977fb09e55603eee6fb53bdd76ee9c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e4545b55904ebef470423d3ddddb74fa7325497a", - "reference": "e4545b55904ebef470423d3ddddb74fa7325497a", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ee5d8f2d3977fb09e55603eee6fb53bdd76ee9c1", + "reference": "ee5d8f2d3977fb09e55603eee6fb53bdd76ee9c1", "shasum": "" }, "require": { @@ -3006,7 +3005,7 @@ "type": "tidelift" } ], - "time": "2023-08-08T12:33:42+00:00" + "time": "2023-08-14T13:24:11+00:00" }, { "name": "phpunit/php-code-coverage", diff --git a/src/Admin/Editor.php b/src/Admin/Editor.php index 046839e4..3df834ff 100644 --- a/src/Admin/Editor.php +++ b/src/Admin/Editor.php @@ -22,6 +22,7 @@ class Editor { public function admin_init() { add_filter( 'wp_insert_post_data', [ $this, 'validate_and_pre_save_cb' ], 10, 2 ); add_action( sprintf( 'save_post_%s', Document::TYPE_NAME ), [ $this, 'save_document_cb' ], 10, 3 ); + add_action( 'untrashed_post', [ $this, 'untrashed_post_cb' ], 10, 2 ); // Enable excerpts for the persisted query post type for the wp admin editor add_post_type_support( Document::TYPE_NAME, 'excerpt' ); @@ -35,6 +36,25 @@ public function admin_init() { add_filter( 'wp_editor_settings', [ $this, 'wp_editor_settings' ], 10, 2 ); } + /** + * Fires after a post is restored from the Trash. + * + * @param int $post_id Post ID. + * @param string $previous_status The status of the post at the point where it was trashed. + * @return void + */ + public function untrashed_post_cb( $post_id, $previous_status ) { + // If have errors when validating the post content/data, do not show those in the admin when untrash. + $untrashed_post = get_post( $post_id ); + + // Bail if the untrashed post is not a GraphQL Document + if ( ! isset( $untrashed_post->post_type ) || Document::TYPE_NAME !== $untrashed_post->post_type ) { + return; + } + + delete_transient( AdminErrors::TRANSIENT_NAME ); + } + /** * If existing post is edited, verify query string in content is valid graphql * @@ -47,22 +67,44 @@ public function validate_and_pre_save_cb( $data, $post ) { return $data; } + if ( 'trash' === $post['post_status'] ) { + return $data; + } + $document = new Document(); try { - if ( array_key_exists( 'post_content', $post ) && 'publish' === $post['post_status'] ) { - $data['post_content'] = $document->valid_or_throw( $post['post_content'], $post['ID'] ); + // Check for empty post_content when publishing the query and throw + if ( 'publish' === $post['post_status'] && empty( $post['post_content'] ) ) { + throw new RequestError( __( 'Query string is empty', 'wp-graphql-smart-cache' ) ); } + + $data['post_content'] = $document->valid_or_throw( $post['post_content'], $post['ID'] ); + } catch ( RequestError $e ) { AdminErrors::add_message( $e->getMessage() ); - // Overwrite new/invalid query with previous working query, or empty - $existing_post = get_post( $post['ID'] ); - if ( $existing_post && property_exists( $existing_post, 'post_content' ) ) { - try { - $data['post_content'] = $document->valid_or_throw( $existing_post->post_content, $post['ID'] ); - } catch ( RequestError $e ) { - $data['post_content'] = ''; + // If encountered invalid data when publishing query, revert some data. If draft, allow invalid query. + if ( 'publish' === $post['post_status'] ) { + + // If has an existing published post and trying to publish with errors, bail before save_post + $existing_post = get_post( $post['ID'], ARRAY_A ); + if ( $existing_post && 'publish' === $existing_post['post_status'] ) { + + wp_safe_redirect( admin_url( sprintf( '/post.php?post=%d&action=edit', $post['ID'] ) ) ); + exit; + + } else { + $data['post_status'] = 'draft'; + + // This prevents the Admin UI from showing that the post has previously been published (because it actually hasn't been) + if ( isset( $existing_post['post_date'] ) && isset( $existing_post['post_date_gmt'] ) && '0000-00-00 00:00:00' !== $existing_post['post_date_gmt'] ) { + $data['post_date'] = $existing_post['post_date']; + $data['post_date_gmt'] = get_gmt_from_date( $existing_post['post_date'] ); + } else { + // Clearing this is same as removing the publish date. + $data['post_date_gmt'] = '0000-00-00 00:00:00'; + } } } } @@ -129,6 +171,10 @@ public function save_document_cb( $post_id, $post, $update ) { return; } + if ( 'trash' === $post->post_status ) { + return; + } + if ( ! $this->is_valid_form( $post_id ) ) { return; } diff --git a/src/AdminErrors.php b/src/AdminErrors.php index 48a2fa28..7be78417 100644 --- a/src/AdminErrors.php +++ b/src/AdminErrors.php @@ -19,6 +19,7 @@ class AdminErrors { */ public function init() { add_action( 'admin_notices', [ $this, 'display_validation_messages' ] ); + add_filter( 'post_updated_messages', [ $this, 'post_updated_messages_cb' ] ); } /** @@ -63,4 +64,22 @@ public function display_validation_messages() { delete_transient( self::TRANSIENT_NAME ); } + + /** + * Filters the post updated messages. + * + * @param array[] $messages Post updated messages. + * @return array[] + */ + public function post_updated_messages_cb( $messages ) { + // If have admin error message, don't display the 'Post Published' message for this post type + $error_messages = get_transient( self::TRANSIENT_NAME ); + if ( ! empty( $error_messages ) ) { + // phpcs:ignore + $message_number = isset( $_GET['message'] ) ? absint( $_GET['message'] ) : 0; + $messages[ Document::TYPE_NAME ][ $message_number ] = ''; + } + + return $messages; + } } diff --git a/tests/acceptance/QueryIdCest.php b/tests/acceptance/QueryIdCest.php index 9d9efdce..589998c1 100644 --- a/tests/acceptance/QueryIdCest.php +++ b/tests/acceptance/QueryIdCest.php @@ -2,42 +2,56 @@ class QueryIdCest { - public function queryIdThatDoesNotExistTest(AcceptanceTester $I) - { - $I->sendGet('graphql', [ 'queryId' => '1234' ] ); - $I->seeResponseContainsJson([ - 'errors' => [ - 'message' => 'PersistedQueryNotFound' - ] - ]); - } - - public function saveQueryAndHashTest(AcceptanceTester $I) - { - $I->sendPost('graphql', [ - 'query' => '{__typename}', - 'queryId' => '8d8f7365e9e86fa8e3313fcaf2131b801eafe9549de22373089cf27511858b39' - ] ); - $I->seeResponseContainsJson([ - 'data' => [ - '__typename' => 'RootQuery' - ] - ]); + public function queryIdThatDoesNotExistTest(AcceptanceTester $I) + { + $I->sendGet('graphql', [ 'queryId' => '1234' ] ); + $I->seeResponseContainsJson([ + 'errors' => [ + 'message' => 'PersistedQueryNotFound' + ] + ]); + } + + // If send empty string and a query id that does not exist, will get not found error + public function sendEmptyQueryStringWithQueryIdIsErrorTest(AcceptanceTester $I) + { + $I->sendPost('graphql', [ + 'query' => '', + 'queryId' => 'alias-does-not-exist' + ] ); + $I->seeResponseContainsJson([ + 'errors' => [ + 'message' => 'PersistedQueryNotFound' + ] + ]); + } + + public function saveQueryAndHashTest(AcceptanceTester $I) + { + $I->sendPost('graphql', [ + 'query' => '{__typename}', + 'queryId' => '8d8f7365e9e86fa8e3313fcaf2131b801eafe9549de22373089cf27511858b39' + ] ); + $I->seeResponseContainsJson([ + 'data' => [ + '__typename' => 'RootQuery' + ] + ]); - $I->sendPost('graphql', [ - 'query' => '{ __typename }', - 'extensions' => [ - "persistedQuery" => [ - "version" => 1, - "sha256Hash" => "8d8f7365e9e86fa8e3313fcaf2131b801eafe9549de22373089cf27511858b39" - ] - ] - ] ); - $I->seeResponseContainsJson([ - 'data' => [ - '__typename' => 'RootQuery' - ] - ]); - } + $I->sendPost('graphql', [ + 'query' => '{ __typename }', + 'extensions' => [ + "persistedQuery" => [ + "version" => 1, + "sha256Hash" => "8d8f7365e9e86fa8e3313fcaf2131b801eafe9549de22373089cf27511858b39" + ] + ] + ] ); + $I->seeResponseContainsJson([ + 'data' => [ + '__typename' => 'RootQuery' + ] + ]); + } } diff --git a/tests/functional/AdminEditorDocumentCest.php b/tests/functional/AdminEditorDocumentCest.php index 8c3985a7..eec41963 100644 --- a/tests/functional/AdminEditorDocumentCest.php +++ b/tests/functional/AdminEditorDocumentCest.php @@ -7,6 +7,16 @@ class AdminEditorDocumentCest { public function _before( FunctionalTester $I ) { + // Enable the show-in-ui for these tests. This allows testing of the admin editor page for our post type. + $I->haveOptionInDatabase( 'graphql_persisted_queries_section', [ 'editor_display' => 'on' ] ); + } + + public function _after( FunctionalTester $I ) { + $I->dontHaveOptionInDatabase( 'graphql_persisted_queries_section' ); + + // Clean up any saved query documents + $I->dontHavePostInDatabase( [ 'post_type' => 'graphql_document' ] ); + $I->dontHaveTermInDatabase( [ 'taxonomy' => 'graphql_query_alias'] ); } /** @@ -17,9 +27,6 @@ public function _before( FunctionalTester $I ) { */ public function postTypeShouldNotBePublicQueryableTest( FunctionalTester $I ) { - // Enable the show-in-ui for these tests. This allows testing of the admin editor page for our post type. - $I->haveOptionInDatabase( 'graphql_persisted_queries_section', [ 'editor_display' => 'on' ] ); - // Create a query in the admin editor $I->loginAsAdmin(); $I->amOnPage( '/wp-admin/post-new.php?post_type=graphql_document'); @@ -37,7 +44,6 @@ public function postTypeShouldNotBePublicQueryableTest( FunctionalTester $I ) { // saved document should not be visible $I->amOnPage( "/graphql_document/test-query-foo/" ); - codecept_debug( $I->grabPageSource() ); $I->dontSee('__typename'); // WordPress shows the homepage template for taxonomies that are public=>false @@ -52,7 +58,6 @@ public function postTypeShouldNotBePublicQueryableTest( FunctionalTester $I ) { // query alias should not be visible $I->amOnPage( "/graphql_query_alias/test-document-foo-bar/" ); - codecept_debug( $I->grabPageSource() ); $I->dontSee('Alias Name: test-query-foo'); $I->seeElement( "//body[contains(@class,'home')]" ); @@ -63,7 +68,6 @@ public function postTypeShouldNotBePublicQueryableTest( FunctionalTester $I ) { // allow/deny grant should not be visible $I->amOnPage( "/graphql_document_grant/allow/" ); - codecept_debug( $I->grabPageSource() ); $I->dontSee('Allow/Deny: allow'); // tax-graphql_document_grant $I->dontSeeElement( "//body[contains(@class,'tax-graphql_document_grant')]" ); @@ -86,4 +90,401 @@ public function postTypeShouldNotBePublicQueryableTest( FunctionalTester $I ) { $I->seeElement( "//body[contains(@class,'error404')]" ); $I->dontSee('XML Sitemap'); } + + public function createNewQueryWithoutErrorWhenSaveDraftSavesAsDraftTest( FunctionalTester $I ) { + $post_title = 'test-post'; + $normalized_query_string = "{\n __typename\n}\n"; + + // Create a new query in the admin editor + $I->loginAsAdmin(); + $I->amOnPage( '/wp-admin/post-new.php?post_type=graphql_document'); + + // Add title should trigger auto-draft, but not save document + $I->fillField( "//input[@name='post_title']", $post_title ); + $I->fillField( 'content', '{ __typename }'); + + // This might cause auto-draft but not save + $I->dontSeePostInDatabase( ['post_title' => $post_title] ); + + // Save draft button. + $I->click('Save Draft'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'draft', + 'post_content' => $normalized_query_string, + ]); + + $I->seeElement('//*[@id="message"]'); + $I->see('Post draft updated.', '//*[@id="message"]'); + $I->see('Publish immediately'); // does not have a publish date + } + + public function createNewQueryWithEmptyContentWhenSaveDraftSavesAsDraftTest( FunctionalTester $I ) { + $post_title = 'test-post'; + + // Create a new query in the admin editor + $I->loginAsAdmin(); + $I->amOnPage( '/wp-admin/post-new.php?post_type=graphql_document'); + + // Add title should trigger auto-draft, but not save document + $I->fillField( "//input[@name='post_title']", $post_title ); + + $I->dontSeePostInDatabase( ['post_title' => $post_title] ); + + // Save draft button. No content in form + $I->click('Save Draft'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'draft', + 'post_content' => '', + ]); + + $I->seeElement('//*[@id="message"]'); + $I->see('Post draft updated.', '//*[@id="message"]'); + $I->see('Publish immediately'); // does not have a publish date + } + + public function createNewQueryWithEmptyContentWhenPublishSavesAsDraftTest( FunctionalTester $I ) { + $post_title = 'test-post'; + + // Create a new query in the admin editor + $I->loginAsAdmin(); + $I->amOnPage( '/wp-admin/post-new.php?post_type=graphql_document'); + + // Add title should trigger auto-draft, but not save document + $I->fillField( "//input[@name='post_title']", $post_title ); + $I->fillField( 'content', ''); + + $I->dontSeePostInDatabase( ['post_title' => $post_title] ); + + // Publish post + $I->click('#publish'); + + // Because of error form (empty content), saves as draft + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'draft', + 'post_content' => '', + ]); + + $I->dontSeeElement('//*[@id="message"]'); + $I->dontSee('Post draft updated.'); + $I->dontSee('Post published.'); + $I->see('Publish immediately'); // does not have a publish date + } + + public function createNewQueryWithInvalidContentWhenPublishSavesAsDraftTest( FunctionalTester $I ) { + $post_title = 'test-post'; + + // Create a new query in the admin editor + $I->loginAsAdmin(); + $I->amOnPage( '/wp-admin/post-new.php?post_type=graphql_document'); + + // Add title should trigger auto-draft, but not save document + $I->fillField( "//input[@name='post_title']", $post_title ); + $I->fillField( 'content', '{ __typename broken'); + + // This should cause auto-draft but not save + $I->dontSeePostInDatabase( ['post_title' => $post_title] ); + + // Publish post + $I->click('#publish'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'draft', + 'post_content' => '{ __typename broken', + ]); + + $I->dontSeeElement('//*[@id="message"]'); + $I->dontSee('Post draft updated.'); + $I->dontSee('Post published.'); + $I->see('Publish immediately'); // does not have publish date + } + + public function createNewQueryWithoutErrorWhenPublishSavesAsPublishedTest( FunctionalTester $I ) { + $post_title = 'test-post'; + $normalized_query_string = "{\n __typename\n}\n"; + + // Create a new query in the admin editor + $I->loginAsAdmin(); + $I->amOnPage( '/wp-admin/post-new.php?post_type=graphql_document'); + + // // Add title should trigger auto-draft, but not save document + $I->fillField( "//input[@name='post_title']", $post_title ); + $I->fillField( 'content', '{ __typename }'); + + // // This might cause auto-draft but not save + $I->dontSeePostInDatabase( ['post_title' => $post_title] ); + + // Publish post + $I->click('#publish'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'publish', + 'post_content' => $normalized_query_string, + ]); + + $I->seeElement('//*[@id="message"]'); + $I->see('Post published.', '//*[@id="message"]'); + $I->dontSee('Publish immediately'); // has publish date + } + + public function haveDraftQueryWithInvalidQueryWhenPublishSavesAsDraftTest( FunctionalTester $I ) { + $post_title = 'test-post'; + $normalized_query_string = "{\n __typename\n}\n"; + + // Create a new query in the admin editor + $I->loginAsAdmin(); + $I->amOnPage( '/wp-admin/post-new.php?post_type=graphql_document'); + + // Add title should trigger auto-draft, but not save document + $I->fillField( "//input[@name='post_title']", $post_title ); + $I->fillField( 'content', '{ __typename }'); + + // Save draft button. + $I->click('Save Draft'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'draft', + 'post_content' => $normalized_query_string, + ]); + + // invalid query + $I->fillField( 'content', '{ __typename broken'); + + // // Publish post button + $I->click('#publish'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'draft', + 'post_content' => '{ __typename broken', + ]); + + $I->dontSeeElement('//*[@id="message"]'); + $I->dontSee('Post draft updated.'); + $I->dontSee('Post published.'); + $I->see('Publish immediately'); // does not have publish date + } + + public function haveDraftQueryWithValidQueryWhenPublishSavesAsPublishedTest( FunctionalTester $I ) { + $post_title = 'test-post'; + $normalized_query_string = "{\n __typename\n}\n"; + + // Create a new query in the admin editor + $I->loginAsAdmin(); + $I->amOnPage( '/wp-admin/post-new.php?post_type=graphql_document'); + + // Add title should trigger auto-draft, but not save document + $I->fillField( "//input[@name='post_title']", $post_title ); + $I->fillField( 'content', '{ __typename }'); + + // Save draft button. + $I->click('Save Draft'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'draft', + 'post_content' => $normalized_query_string, + ]); + + // invalid query + $I->fillField( 'content', '{ posts { edges { node { id } } } }'); + + // // Publish post button + $I->click('#publish'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'publish', + 'post_content' => "{\n posts {\n edges {\n node {\n id\n }\n }\n }\n}\n", + ]); + + $I->seeElement('//*[@id="message"]'); + $I->see('Post published.', '//*[@id="message"]'); + $I->dontSee('Publish immediately'); // has publish date + } + + public function havePublishedQueryWhenSaveDraftWithInvalidQuerySavesAsDraftTest( FunctionalTester $I ) { + $post_title = 'test-post'; + $normalized_query_string = "{\n __typename\n}\n"; + + // Create a new query in the admin editor + $I->loginAsAdmin(); + $I->amOnPage( '/wp-admin/post-new.php?post_type=graphql_document'); + + // Add title should trigger auto-draft, but not save document + $I->fillField( "//input[@name='post_title']", $post_title ); + $I->fillField( 'content', '{ __typename }'); + + // Publish post + $I->click('#publish'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'publish', + 'post_content' => $normalized_query_string, + ]); + + // invalid query + $I->fillField( 'content', '{ __typename broken'); + + // Change to draft status + $I->selectOption('#post_status', 'Draft'); + + // // Publish post button + $I->click('#publish'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'draft', + 'post_content' => '{ __typename broken', + ]); + + $I->dontSeeElement('//*[@id="message"]'); + $I->dontSee('Post published.'); + $I->dontSee('Post updated.'); + $I->dontSee('Post saved.'); + $I->dontSee('Publish immediately'); // has date because already published + } + + public function havePublishedQueryWhenSaveDraftWithValidQuerySavesAsDraftTest( FunctionalTester $I ) { + $post_title = 'test-post'; + $normalized_query_string = "{\n __typename\n}\n"; + + // Create a new query in the admin editor + $I->loginAsAdmin(); + $I->amOnPage( '/wp-admin/post-new.php?post_type=graphql_document'); + + // Add title should trigger auto-draft, but not save document + $I->fillField( "//input[@name='post_title']", $post_title ); + $I->fillField( 'content', '{ __typename }'); + + // Publish post + $I->click('#publish'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'publish', + 'post_content' => $normalized_query_string, + ]); + + // invalid query + $I->fillField( 'content', '{ posts { edges { node { id } } } }'); + + // Change to draft status + $I->selectOption('#post_status', 'Draft'); + + // // Publish post button + $I->click('#publish'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'draft', + 'post_content' => "{\n posts {\n edges {\n node {\n id\n }\n }\n }\n}\n", + ]); + + $I->seeElement('//*[@id="message"]'); + $I->see('Post draft updated.', '//*[@id="message"]'); + $I->dontSee('Publish immediately'); // has date because already published + } + + public function havePublishedQueryWithInvalidQueryWhenPublishItShowsPreviousQueryContentTest( FunctionalTester $I ) { + $post_title = 'test-post'; + $original_query = '{ __typename }'; + $normalized_query_string = "{\n __typename\n}\n"; + + // Create a new query in the admin editor + $I->loginAsAdmin(); + $I->amOnPage( '/wp-admin/post-new.php?post_type=graphql_document'); + + // Add title should trigger auto-draft, but not save document + $I->fillField( "//input[@name='post_title']", $post_title); + $I->fillField( 'content', $original_query); + + // Publish post + $I->click('#publish'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'publish', + 'post_content' => $normalized_query_string, + ]); + + // invalid query + $I->fillField( 'content', '{ __typename broken'); + + // // Publish post button + $I->click('#publish'); + + // Does not save/overwrite the working query string with broken one. + // Leaves as published + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'publish', + 'post_content' => $normalized_query_string, + ]); + + $I->dontSeeElement('//*[@id="message"]'); + $I->dontSee('Post published.'); + $I->dontSee('Post updated.'); + $I->dontSee('Post saved.'); + $I->dontSee('Publish immediately'); // has date because already published + } + + public function createNewQueryWithInvalidContentThenTrashItTest( FunctionalTester $I ) { + $post_title = 'test-post'; + + // Create a new query in the admin editor + $I->loginAsAdmin(); + $I->amOnPage( '/wp-admin/post-new.php?post_type=graphql_document'); + + // Add title should trigger auto-draft, but not save document + $I->fillField( "//input[@name='post_title']", $post_title ); + $I->fillField( 'content', '{ __typename broken'); + + // Save draft button. + $I->click('Save Draft'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'draft', + 'post_content' => '{ __typename broken', + ]); + + // should see our admin error + $I->seeElement('//*[@id="plugin-message"]'); + $I->see('Invalid graphql query string "{ __typename broken"', '//*[@id="plugin-message"]'); + + $I->click('Move to Trash'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'trash', + 'post_content' => '{ __typename broken', + ]); + + // should not see our admin error + $I->dontSeeElement('//*[@id="plugin-message"]'); + $I->dontSee('Invalid graphql query string "{ __typename broken"', '//*[@id="plugin-message"]'); + + // Go to list of saved documents in trash. Restore to 'untrash' it. + $I->amOnPage('/wp-admin/edit.php?post_status=trash&post_type=graphql_document'); + $I->click('Restore'); + + $I->seePostInDatabase( [ + 'post_title' => $post_title, + 'post_status' => 'draft', + 'post_content' => '{ __typename broken', + ]); + + // should not see our admin error + $I->dontSeeElement('//*[@id="plugin-message"]'); + $I->dontSee('Invalid graphql query string "{ __typename broken"', '//*[@id="plugin-message"]'); + } } diff --git a/tests/functional/AdminSettingsCacheCest.php b/tests/functional/AdminSettingsCacheCest.php index 8b9de078..0dd52cd6 100644 --- a/tests/functional/AdminSettingsCacheCest.php +++ b/tests/functional/AdminSettingsCacheCest.php @@ -11,17 +11,17 @@ public function _after( FunctionalTester $I ) { } public function selectCacheSettingsTest( FunctionalTester $I ) { - $I->loginAsAdmin(); - $I->amOnPage('/wp-admin/admin.php?page=graphql-settings#graphql_cache_section'); + $I->loginAsAdmin(); + $I->amOnPage('/wp-admin/admin.php?page=graphql-settings#graphql_cache_section'); - // Save and see the selection after form submit - $I->checkOption("//input[@type='checkbox' and @name='graphql_cache_section[cache_toggle]']"); - $I->click('Save Changes'); - $I->seeCheckboxIsChecked("//input[@type='checkbox' and @name='graphql_cache_section[cache_toggle]']"); + // Save and see the selection after form submit + $I->checkOption("//input[@type='checkbox' and @name='graphql_cache_section[cache_toggle]']"); + $I->click('Save Changes'); + $I->seeCheckboxIsChecked("//input[@type='checkbox' and @name='graphql_cache_section[cache_toggle]']"); - $I->uncheckOption("//input[@type='checkbox' and @name='graphql_cache_section[cache_toggle]']"); - $I->click('Save Changes'); - $I->dontSeeCheckboxIsChecked("//input[@type='checkbox' and @name='graphql_cache_section[cache_toggle]']"); + $I->uncheckOption("//input[@type='checkbox' and @name='graphql_cache_section[cache_toggle]']"); + $I->click('Save Changes'); + $I->dontSeeCheckboxIsChecked("//input[@type='checkbox' and @name='graphql_cache_section[cache_toggle]']"); } public function saveCacheTllExpirationTest( FunctionalTester $I ) {