diff --git a/tests/EndToEnd/general/plugin-screens/PluginSettingsToolsImporterKitLegacyFormsCest.php b/tests/EndToEnd/general/plugin-screens/PluginSettingsToolsImporterKitLegacyFormsCest.php new file mode 100644 index 000000000..f8ed99e6d --- /dev/null +++ b/tests/EndToEnd/general/plugin-screens/PluginSettingsToolsImporterKitLegacyFormsCest.php @@ -0,0 +1,230 @@ + Kit > Tools > Import sections for Kit Legacy Forms. + * + * @since 3.3.5 + */ +class PluginSettingsToolsImporterKitLegacyFormsCest +{ + /** + * Run common actions before running the test functions in this class. + * + * @since 3.3.5 + * + * @param EndToEndTester $I Tester. + */ + public function _before(EndToEndTester $I) + { + // Activate Plugin. + $I->activateKitPlugin($I); + } + + /** + * Test that Kit Legacy Form Shortcodes are replaced with Kit Form Shortcodes when the Tools > Kit Legacy Forms: Migrate Configuration is configured. + * + * @since 3.3.5 + * + * @param EndToEndTester $I Tester. + */ + public function testKitLegacyFormsImportWithShortcodes(EndToEndTester $I) + { + // Setup Plugin. + $I->setupKitPlugin($I); + $I->setupKitPluginResources($I); + + // Insert Kit Legacy Form Shortcode into Page. + $pageID = $this->_createPageWithKitLegacyFormShortcodes($I, $_ENV['CONVERTKIT_API_LEGACY_FORM_ID']); + + // Navigate to the Tools screen. + $I->loadKitSettingsToolsScreen($I); + + // Select the Kit Form to replace the Kit Legacy Form. + $I->selectOption('_wp_convertkit_integration_convertkit_legacy_forms_settings[' . $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'] . ']', $_ENV['CONVERTKIT_API_FORM_ID']); + + // Click the Migrate button. + $I->click('Migrate'); + + // Confirm success message displays. + $I->waitForElementVisible('.notice-success'); + $I->see('Kit Legacy Forms migrated successfully.'); + + // View the Page, to confirm Kit Form now displays. + $I->amOnPage('?p=' . $pageID); + $I->seeElementInDOM('form[data-sv-form]'); + } + + /** + * Test that Kit Legacy Form Blocks are replaced with Kit Blocks when the Tools > Kit Legacy Forms: Migrate Configuration is configured. + * + * @since 3.3.5 + * + * @param EndToEndTester $I Tester. + */ + public function testKitLegacyFormsImportWithBlocks(EndToEndTester $I) + { + // Setup Plugin. + $I->setupKitPlugin($I); + $I->setupKitPluginResources($I); + + // Insert Kit Legacy Form Block into Page. + $pageID = $this->_createPageWithKitLegacyFormBlocks($I, $_ENV['CONVERTKIT_API_LEGACY_FORM_ID']); + + // Navigate to the Tools screen. + $I->loadKitSettingsToolsScreen($I); + + // Select the Kit Form to replace the Kit Legacy Form. + $I->selectOption('_wp_convertkit_integration_convertkit_legacy_forms_settings[' . $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'] . ']', $_ENV['CONVERTKIT_API_FORM_ID']); + + // Click the Migrate button. + $I->click('Migrate'); + + // Confirm success message displays. + $I->waitForElementVisible('.notice-success'); + $I->see('Kit Legacy Forms migrated successfully.'); + + // View the Page, to confirm Kit Form block now displays. + $I->amOnPage('?p=' . $pageID); + $I->seeElementInDOM('form[data-sv-form]'); + + // Confirm special characters have not been stripped. + $I->seeInSource('!@£$%^&*()_+~!@£$%^&*()_+\\'); + } + + /** + * Test that the Kit Legacy Forms: Migrate Configuration section is not displayed when no Kit Legacy Forms exist. + * + * @since 3.3.5 + * + * @param EndToEndTester $I Tester. + */ + public function testKitLegacyFormsImportWhenNoKitLegacyForms(EndToEndTester $I) + { + // Setup Plugin. + $I->setupKitPlugin($I); + + // Navigate to the Tools screen. + $I->loadKitSettingsToolsScreen($I); + + // Confirm no Kit Legacy Forms: Migrate Configuration section is displayed. + $I->dontSeeElementInDOM('#import-kit-legacy-forms'); + } + + /** + * Test that the Kit Legacy Forms: Migrate Configuration section is not displayed when Kit Legacy Forms exist, + * but no Pages, Posts or Custom Posts contain Kit Legacy Form Shortcodes. + * + * @since 3.3.5 + * + * @param EndToEndTester $I Tester. + */ + public function testKitLegacyFormsImportWhenNoKitLegacyShortcodesOrBlocksInContent(EndToEndTester $I) + { + // Setup Plugin. + $I->setupKitPlugin($I); + $I->setupKitPluginResources($I); + + // Navigate to the Tools screen. + $I->loadKitSettingsToolsScreen($I); + + // Confirm no Kit Legacy Forms: Migrate Configuration section is displayed, as there are no + // Kit Legacy Form Shortcodes or Blocks in the content. + $I->dontSeeElementInDOM('#import-kit-legacy-forms'); + } + + /** + * Test that the Kit Legacy Forms: Migrate Configuration section is not displayed when no Kit Forms exist. + * + * @since 3.3.5 + * + * @param EndToEndTester $I Tester. + */ + public function testKitLegacyFormsImportWhenNoKitForms(EndToEndTester $I) + { + // Setup Plugin. + $I->setupKitPluginCredentialsNoData($I); + $I->setupKitPluginResourcesNoData($I); + + // Navigate to the Tools screen. + $I->loadKitSettingsToolsScreen($I); + + // Confirm no Kit Legacy Forms: Migrate Configuration section is displayed, as there are no + // Kit Forms exist. + $I->dontSeeElementInDOM('#import-kit-legacy-forms'); + } + + /** + * Create Pages with Kit Legacy Form Shortcodes. + * + * @since 3.3.5 + * + * @param EndToEndTester $I Tester. + * @param int $kitLegacyFormID Kit Legacy Form ID. + * @return int + */ + private function _createPageWithKitLegacyFormShortcodes(EndToEndTester $I, $kitLegacyFormID) + { + return $I->havePostInDatabase( + [ + 'post_type' => 'page', + 'post_status' => 'publish', + 'post_title' => 'Page with Kit Form Shortcode using Legacy Form #' . $kitLegacyFormID, + 'post_content' => '[convertkit_form form="' . $kitLegacyFormID . '"]', + 'meta_input' => [ + '_wp_convertkit_post_meta' => [ + 'form' => '0', + 'landing_page' => '', + 'tag' => '', + ], + ], + ] + ); + } + + /** + * Create Pages with Kit Legacy Form Blocks. + * + * @since 3.3.5 + * + * @param EndToEndTester $I Tester. + * @param int $kitLegacyFormID Kit Legacy Form ID. + * @return int + */ + private function _createPageWithKitLegacyFormBlocks(EndToEndTester $I, $kitLegacyFormID) + { + return $I->havePostInDatabase( + [ + 'post_type' => 'page', + 'post_status' => 'publish', + 'post_title' => 'Page with Kit Form Block using Legacy Form #' . $kitLegacyFormID, + 'post_content' => '
Subscribe to get our latest content by email.
', + 'sign_up_button_text' => 'Subscribe', + 'success_message' => 'Success! Now check your email to confirm your subscription.', + 'archived' => false, + ], + 2780980 => [ + 'id' => 2780980, + 'name' => 'Sticky Bar Form', + 'created_at' => '2021-11-17T04:22:42.000Z', + 'type' => 'embed', + 'format' => 'sticky bar', + 'embed_js' => 'https://cheerful-architect-3237.kit.com/9f5c601482/index.js', + 'embed_url' => 'https://cheerful-architect-3237.kit.com/9f5c601482', + 'archived' => false, + 'uid' => '9f5c601482', + ], + 3437554 => [ + 'id' => 3437554, + 'name' => 'AAA Test', + 'created_at' => '2022-07-15T15:06:32.000Z', + 'type' => 'embed', + 'format' => 'inline', + 'embed_js' => 'https://cheerful-architect-3237.kit.com/3bb15822a2/index.js', + 'embed_url' => 'https://cheerful-architect-3237.kit.com/3bb15822a2', + 'archived' => false, + 'uid' => '3bb15822a2', + ], + 2765149 => [ + 'id' => 2765149, + 'name' => 'WooCommerce Product Form', + 'created_at' => '2021-11-11T15:32:54.000Z', + 'type' => 'embed', + 'format' => 'inline', + 'embed_js' => 'https://cheerful-architect-3237.kit.com/7e238f3920/index.js', + 'embed_url' => 'https://cheerful-architect-3237.kit.com/7e238f3920', + 'archived' => false, + 'uid' => '7e238f3920', + ], + ] + ); } /** @@ -53,6 +173,9 @@ public function tearDown(): void // Deactivate Plugin. deactivate_plugins('convertkit/wp-convertkit.php'); + // Delete the Forms resource. + delete_option( 'convertkit_forms' ); + parent::tearDown(); } @@ -483,6 +606,265 @@ public function testCampaignMonitorReplaceShortcodesInContentIgnoringOtherShortc } } + /** + * Test that the get_form_ids_from_content() method returns Kit legacy form shortcode Form IDs + * ignoring any other shortcodes. + * + * @since 3.3.5 + */ + public function testGetKitLegacyFormsFormIDsFromContent() + { + // Initialize the class we want to test. + $this->importer = new \ConvertKit_Admin_Importer_ConvertKit_Legacy_Forms(); + + // Confirm initialization didn't result in an error. + $this->assertNotInstanceOf(\WP_Error::class, $this->importer); + + // Define the content to test. + $content = 'Legacy Form: [convertkit_form form="' . $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'] . '"] Legacy Form ID: [convertkit_form id="' . $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'] . '"] non-Legacy Form: [convertkit_form form="' . $_ENV['CONVERTKIT_API_FORM_ID'] . '"] Different shortcode: [aweber formid="12"]'; + + // Extract form IDs from content. + $form_ids = $this->importer->get_form_ids_from_content( $content ); + + // Assert the legacy form shortcode was detected, and the non-legacy form shortcode was ignored. + $this->assertEquals( 1, count( $form_ids ) ); + $this->assertEquals( $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'], $form_ids[0] ); + } + + /** + * Test that the replace_shortcodes_in_content() method replaces the Kit legacy form shortcode with the Kit form shortcode. + * + * @since 3.3.5 + */ + public function testKitLegacyFormsReplaceShortcodesInContent() + { + // Initialize the class we want to test. + $this->importer = new \ConvertKit_Admin_Importer_ConvertKit_Legacy_Forms(); + + // Confirm initialization didn't result in an error. + $this->assertNotInstanceOf(\WP_Error::class, $this->importer); + + // Define the shortcodes to test. + $shortcodes = [ + '[convertkit_form form="' . $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'] . '"]', + '[convertkit_form form=' . $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'] . ']', + '[convertkit_form id="' . $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'] . '"]', + '[convertkit_form id=' . $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'] . ']', + ]; + + // Test each shortcode is replaced with the Kit form shortcode. + foreach ( $shortcodes as $shortcode ) { + $this->assertEquals( + '[convertkit_form form="' . $_ENV['CONVERTKIT_API_FORM_ID'] . '"]', + $this->importer->replace_shortcodes_in_content( $shortcode, $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'], $_ENV['CONVERTKIT_API_FORM_ID'] ) + ); + + // Prepend and append some content. + $content = 'Some content before the shortcode: ' . $shortcode . ' Some content after the shortcode.'; + $this->assertEquals( + 'Some content before the shortcode: [convertkit_form form="' . $_ENV['CONVERTKIT_API_FORM_ID'] . '"] Some content after the shortcode.', + $this->importer->replace_shortcodes_in_content( $content, $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'], $_ENV['CONVERTKIT_API_FORM_ID'] ) + ); + + // Prepend and append some content and duplicate the shortcode. + $content = 'Some content before the shortcode: ' . $shortcode . ' Some content after the shortcode: ' . $shortcode; + $this->assertEquals( + 'Some content before the shortcode: [convertkit_form form="' . $_ENV['CONVERTKIT_API_FORM_ID'] . '"] Some content after the shortcode: [convertkit_form form="' . $_ENV['CONVERTKIT_API_FORM_ID'] . '"]', + $this->importer->replace_shortcodes_in_content( $content, $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'], $_ENV['CONVERTKIT_API_FORM_ID'] ) + ); + } + } + + /** + * Test that the replace_shortcodes_in_content() method ignores non-Kit legacy form shortcodes. + * + * @since 3.3.5 + */ + public function testKitLegacyFormsReplaceShortcodesInContentIgnoringOtherShortcodes() + { + // Initialize the class we want to test. + $this->importer = new \ConvertKit_Admin_Importer_ConvertKit_Legacy_Forms(); + + // Confirm initialization didn't result in an error. + $this->assertNotInstanceOf(\WP_Error::class, $this->importer); + + // Define the shortcodes to test. + $shortcodes = [ + '[convertkit_form form="' . $_ENV['CONVERTKIT_API_FORM_ID'] . '"]', + '[convertkit_form id="' . $_ENV['CONVERTKIT_API_FORM_ID'] . '"]', + '[a_random_shortcode]', + ]; + + // Test each shortcode is ignored. + foreach ( $shortcodes as $shortcode ) { + $this->assertEquals( + $shortcode, + $this->importer->replace_shortcodes_in_content( $shortcode, $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'], $_ENV['CONVERTKIT_API_FORM_ID'] ) + ); + } + } + + /** + * Test that the replace_blocks_in_post() method replaces the third party form block with the Kit form block, + * and special characters are not stripped when the Post is saved. + * + * @since 3.3.5 + */ + public function testKitLegacyFormsReplaceBlocksInPost() + { + // Initialize the class we want to test. + $this->importer = new \ConvertKit_Admin_Importer_ConvertKit_Legacy_Forms(); + + // Confirm initialization didn't result in an error. + $this->assertNotInstanceOf(\WP_Error::class, $this->importer); + + // Create a Post with a MC4WP form block and HTML block, as if the user already created this post. + $postID = $this->factory->post->create( + [ + 'post_type' => 'page', + 'post_status' => 'publish', + 'post_title' => 'Kit Legacy Forms: Replace Blocks in Post', + 'post_content' => str_replace( '\\', '\\\\', '' . $this->html_block ), + ] + ); + + // Replace the blocks in the post. + $this->importer->replace_blocks_in_post( $postID, $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'], $_ENV['CONVERTKIT_API_FORM_ID'] ); + + // Test the block is replaced with the Kit form block, and special characters are not stripped. + $this->assertEquals( + '' . $this->html_block, + get_post_field( 'post_content', $postID ) + ); + } + + /** + * Test that the replace_blocks_in_content() method replaces the third party form block with the Kit form block, + * and special characters are not stripped. + * + * @since 3.3.5 + */ + public function testKitLegacyFormsReplaceBlocksInContent() + { + // Initialize the class we want to test. + $this->importer = new \ConvertKit_Admin_Importer_ConvertKit_Legacy_Forms(); + + // Confirm initialization didn't result in an error. + $this->assertNotInstanceOf(\WP_Error::class, $this->importer); + + // Define the blocks to test. + $content = '' . $this->html_block; + + // Test the block is replaced with the Kit form block. + $this->assertEquals( + '' . $this->html_block, + $this->importer->replace_blocks_in_content( parse_blocks( $content ), $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'], $_ENV['CONVERTKIT_API_FORM_ID'] ) + ); + } + + /** + * Test that get_form_ids_from_content() returns Kit legacy form block Form IDs + * (in addition to shortcode Form IDs), ignoring any non-legacy Kit form blocks. + * + * Exercises the block-extraction extension to the get_form_ids_from_content() + * override on the Kit Legacy Forms importer. + * + * @since 3.3.5 + */ + public function testGetKitLegacyFormsFormIDsFromContentForBlocks() + { + // Initialize the class we want to test. + $this->importer = new \ConvertKit_Admin_Importer_ConvertKit_Legacy_Forms(); + + // Confirm initialization didn't result in an error. + $this->assertNotInstanceOf(\WP_Error::class, $this->importer); + + // Define content containing both legacy and non-legacy Kit form blocks, + // plus a legacy shortcode, to confirm both block and shortcode IDs are + // surfaced when they reference a legacy form. + $content = '' + . '' + . '[convertkit_form form="' . $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'] . '"]'; + + // Extract form IDs from content. + $form_ids = $this->importer->get_form_ids_from_content( $content ); + + // Assert only the legacy form ID is returned (deduplicated across the + // shortcode and block references). + $this->assertCount( 1, $form_ids ); + $this->assertEquals( (string) $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'], $form_ids[0] ); + } + + /** + * Test that get_forms_in_posts() only returns post IDs whose content + * contains a Kit Form shortcode or block referencing a legacy form ID. + * + * Exercises the get_forms_in_posts() override on the Kit Legacy Forms + * importer, which narrows the parent class's broad SQL match. + * + * @since 3.3.5 + */ + public function testGetKitLegacyFormsInPosts() + { + // Initialize the class we want to test. + $this->importer = new \ConvertKit_Admin_Importer_ConvertKit_Legacy_Forms(); + + // Confirm initialization didn't result in an error. + $this->assertNotInstanceOf(\WP_Error::class, $this->importer); + + // Create a post containing a non-legacy Kit Form shortcode. + $nonLegacyShortcodePostID = $this->factory->post->create( + [ + 'post_type' => 'page', + 'post_status' => 'publish', + 'post_title' => 'Kit Legacy Forms: Non-Legacy Shortcode Post', + 'post_content' => '[convertkit_form form="' . $_ENV['CONVERTKIT_API_FORM_ID'] . '"]', + ] + ); + + // Create a post containing a non-legacy Kit Form block. + $nonLegacyBlockPostID = $this->factory->post->create( + [ + 'post_type' => 'page', + 'post_status' => 'publish', + 'post_title' => 'Kit Legacy Forms: Non-Legacy Block Post', + 'post_content' => '', + ] + ); + + // Create a post containing a legacy Kit Form shortcode. + $legacyShortcodePostID = $this->factory->post->create( + [ + 'post_type' => 'page', + 'post_status' => 'publish', + 'post_title' => 'Kit Legacy Forms: Legacy Shortcode Post', + 'post_content' => '[convertkit_form form="' . $_ENV['CONVERTKIT_API_LEGACY_FORM_ID'] . '"]', + ] + ); + + // Create a post containing a legacy Kit Form block. + $legacyBlockPostID = $this->factory->post->create( + [ + 'post_type' => 'page', + 'post_status' => 'publish', + 'post_title' => 'Kit Legacy Forms: Legacy Block Post', + 'post_content' => '', + ] + ); + + // Fetch the list of post IDs that contain a legacy Kit form reference. + $post_ids = $this->importer->get_forms_in_posts(); + + // Cast post IDs to ints for comparison (wpdb returns strings). + $post_ids = array_map( 'intval', $post_ids ); + + // Assert only the legacy posts are returned, and the non-legacy posts are not. + $this->assertContains( $legacyShortcodePostID, $post_ids ); + $this->assertContains( $legacyBlockPostID, $post_ids ); + $this->assertNotContains( $nonLegacyShortcodePostID, $post_ids ); + $this->assertNotContains( $nonLegacyBlockPostID, $post_ids ); + } + /** * Test that the get_form_ids_from_content() method returns MC4WP form shortcode Form IDs * ignoring any other shortcodes.