The path to an automagical multisite switch 04

Wrapping up a first working iteration.

What for?

My recent coding effort on WP Browser has had a singular focus: to be able to set up complex fixtures in acceptance testing without having to rely on the UI.
Final in this effort is the ability to go from a WordPress single site installation to a multi site one in a matter of one method.
The WPLoader module supports it on a functional level (a configuration value) but a similar approach was missing on the acceptance side of things.
I often use a *Db modules in conjunction with the WPBrowser or WPWebDriver ones to set up a test fixture.
Setting up acceptance fixtures relying on the same UI the test is supposed to test and exercise is a slow and error prone process that’s going to fail in the set up phase whenever that same UI changes.
Tests should fail for one reason only and not while setting up the test fixture.
In the context of WordPress setting up a database to have 6 posts of a custom post type in it and 6 more of another type would require driving the browser (PhpBrowser, PhantomJs, Selenium or whatever) through the WordPress back-end admin screens, click “Add New” for each post, fill some fields and update.
Methods like the ones the WPDb module currently provides make this similar to what can be done in functional tests

$I->haveManyPostsInDatabase(6, 
    [
        'post_type' => 'my_post_type',
        'post_title' => 'My Custom Post Type {{n}}'
    ]);

Where’s the multisite button?

Even wanting to follow a “proper” path to set up a multisite WordPress installation there is no UI provided for it.
WordPress leap from single to multisite installation requires some “scary” operations like modifying the wp-config.php file and the .htaccess one; while the typical user will have that done for him someone willing to test his/her theme or plugin code against a single and multisite installation as well would need to have two distinct local WordPress installations and configurations to do so.
Not to mention the separate testing environments that have to be kept in sync.
I’ve tried using Codeception Environments but that will involve using plugins symbolically linked; it works and can be done but it’s not a “5 minute set up”.
While WPDb latest addition will not provide a multisite button it will provide something that comes, in testing terms, as close as possible; given a single installation site I was able to run this test and get the green:

class WPDbSubdomainMultisiteCest {

    public function _before( AcceptanceTester $I ) {
    }

    public function _after( AcceptanceTester $I ) {
    }

    /**
     * @test
     * it should not activate multisite by default
     */
    public function it_should_not_activate_multisite_by_default( AcceptanceTester $I ) {
        // Set the theme to the `multisite` test theme
        $I->haveOptionInDatabase( 'stylesheet', 'multisite', 'yes' );
        $I->haveOptionInDatabase( 'template', 'multisite', 'yes' );

        $I->amOnPage( '/' );

        // using a test theme that will expose that information in a section on the index
        $I->see( 'Multisite is not active' );
    }

    /**
     * @test
     * it should be able to activate multisite
     */
    public function it_should_be_able_to_activate_multisite( AcceptanceTester $I ) {
        // Set the theme to the `multisite` test theme
        $I->haveOptionInDatabase( 'stylesheet', 'multisite', 'yes' );
        $I->haveOptionInDatabase( 'template', 'multisite', 'yes' );

        // subdomain, need htaccess and config files replaced
        $I->haveMultisiteInDatabase( true, true );

        $I->amOnPage( '/' );

        // using a test theme that will expose that information in a section on the index
        $I->see( 'Multisite is active' );
    }

    /**
     * @test
     * it should allow seing posts from different blogs
     */
    public function it_should_allow_seing_posts_from_different_blogs( AcceptanceTester $I ) {
        // Set the theme to the `multisite` test theme
        $I->haveOptionInDatabase( 'stylesheet', 'multisite', 'yes' );
        $I->haveOptionInDatabase( 'template', 'multisite', 'yes' );

        // subdomain, need htaccess and config files replaced
        $I->haveMultisiteInDatabase( true, true );

        $blogIds = $I->haveManyBlogsInDatabase( 3, [ 'domain' => 'test{{n}}' ] );

        for ( $i = 0; $i < 3; $i++ ) {
            $I->seeBlogInDatabase( [ 'domain' => 'test' . $i . '.' . $I->getSiteDomain() ] );
        }

        // Handlebars syntax here
        foreach ( $blogIds as $blogId ) {
            $I->useBlog( $blogId );
            $I->haveManyPostsInDatabase( 3, [
                'post_title'    => 'Blog {{blog}} - Post {{n}}',
                'template_data' => [ 'blog' => $blogId ]
            ] );
        }

        for ( $i = 0; $i < 3; $i++ ) {
            $blogId = $blogIds[$i];
            $I->amOnSubdomain( 'test' . $i );
            $I->amOnPage( '/' );
            $I->see( "Blog $blogId - Post 0" );
            $I->see( "Blog $blogId - Post 1" );
            $I->see( "Blog $blogId - Post 2" );
        }
    }
}

haveMultisiteInDatabase

Inner workings

In short terms the three requirements of a WordPress multisite installation are being covered scaffolding the missing tables on the database and replacing the wp-config.php and .htaccess files of the local installation with some default ones.
While the approach is not a fine one it provides a running and working solution I’m satisfied with for the time being.

Next

I will clean up the code and tackle the remaining issues and release the new version to the world.

I appreciate your input