Using Posts 2 Posts in WordPress functional tests

A testing gotcha to use the Posts 2 Posts plugin in WordPress functional tests.

The problem

While developing the Posts 2 Posts piping functions of CMB2 Pipes plugin I’ve hit a road-block while trying to work with Posts 2 Posts.
While using WP Browser WP Loader module for functional tests I’ve run into the need to have the Posts 2 Posts plugin up and running before the tests run and it took me some time to figure out how to do it.

A solution

This is the end code I’ve come up with after some iterations:


class TAD_Pipe_P2PPipeTest extends \WP_UnitTestCase {

        protected $backupGlobals = false;

        public static function setUpBeforeClass() {
            self::load_p2p();

            p2p_register_connection_type( [
                'name' => 'post_to_post',
                'from' => 'post',
                'to'   => 'post'
            ] );
        }

        private static function load_p2p() {
            require_once PLUGIN_FOLDER . '/posts-to-posts/posts-to-posts.php';

            $p2p_core = PLUGIN_FOLDER . '/posts-to-posts/core';

            require_once $p2p_core . '/util.php';
            require_once $p2p_core . '/api.php';
            require_once $p2p_core . '/autoload.php';

            P2P_Autoload::register( 'P2P_', $p2p_core );

            P2P_Storage::install();
            P2P_Storage::init();

            P2P_Query_Post::init();
            P2P_Query_User::init();

            P2P_URL_Query::init();
        }

        public function setUp() {
            parent::setUp();

        }

        public function tearDown() {
            // your tear down methods here

            // then
            parent::tearDown();
        }

        /**
         * @test
         * it should just return the field_id if the p2p plugin is not activated
         */
        public function it_should_just_return_the_field_id_if_the_p_2_p_plugin_is_not_activated() {
            deactivate_plugins( 'posts-to-posts/posts-to-posts.php' );

            $this->assertEquals( 'foo', cmb2_p2p_pipe( 'foo', 'p2p_type' ) );
        }

        /**
         * @test
         * it should just return the field if the p2p type is not registered
         */
        public function it_should_just_return_the_field_if_the_p_2_p_type_is_not_registered() {
            $this->assertEquals( 'foo', cmb2_p2p_pipe( 'foo', 'p2p_type' ) );
        }

        /**
         * @test
         * it should relate the post with another post on save
         */
        public function it_should_relate_the_post_with_another_post_on_save() {
            $from_id = $this->factory->post->create();
            $to_id   = $this->factory->post->create();

            $args = [
                'object_id'   => $from_id,
                'object_type' => 'post',
                'field_args'  => [
                    'name' => __( 'p2p relating field', 'cmb2' ),
                    'id'   => cmb2_p2p_pipe( 'related', 'post_to_post' ),
                    'type' => 'select'
                ]
            ];

            $field = new CMB2_Field( $args );

            $field->save_field( $to_id );

            /** @var \wpdb $wpdb */
            global $wpdb;
            $this->assertEquals( 1, $wpdb->get_var( "select count(p2p_id) from $wpdb->p2p where p2p_from = $from_id and p2p_to = $to_id and p2p_type = 'post_to_post'" ) );
        }
    }

The code is complete and running (see the code on GitHub) and what’s different from the use of any other plugin as a test requirement is that Posts 2 Posts will create two custom tables on activation; WordPress tests will wipe the database clean on each run and, furthermore, will not run any activation/deactivation hook.
While the “manual” plugin activation could be done in the bootstrap file I like to have it in the test case to have the test dependencies clear.
I was able to run the test above and can move on with my developement. Posts 2 Posts in functional tests