WPDb multisite capabilities demo 03

Passing a test and writing one more passing test.

What’s this about?

It’s a step by step approach to the new single to multisite and back “hot-swap” possibility introduced in version 1.9 of wp-browser for the WPDb module; it involves creating a theme with a multisite-aware header menu.

Adding the menu id

I have left the test written in the previous post failing on a missing id attribute.

$I = new AcceptanceTester($scenario);
$I->wantTo('see the main-header id on the main site header on a single site');

// set the theme to `_blogs`
$I->haveOptionInDatabase( 'template', 'Twentysixteen' );
$I->haveOptionInDatabase( 'stylesheet', '_blogs' );
$I->haveOptionInDatabase( 'current_theme', '_Blogs' );

// add a nav menu
$menu_id = $I->haveTermInDatabase( 'Menu 1', 'nav_menu', [ 'slug' => 'menu1' ] );

// set theme options to use the `primary` location
$I->haveOptionInDatabase( 'theme_mods__blogs', [ 'nav_menu_locations' => [ 'primary' => $menu_id ] ] );

// add one element to the menu
$menu_item_id = $I->havePostInDatabase( [
    'post_title' => 'theAverageDev',
    'menu_order' => 1,
    'post_type'  => 'nav_menu_item'
] );
$meta         = [
    '_menu_item_type'             => 'custom',
    '_menu_item_object_id'        => $menu_item_id,
    '_menu_item_object'           => 'custom',
    '_menu_item_url'              => 'http://theaveragedev.com'
];
foreach ( $meta as $key => $value ) {
    $I->havePostmetaInDatabase( $menu_item_id, $key, $value );
}

$I->amOnPage('/');
$I->seeElement('div#site-header-menu > nav.main-navigation');
$I->seeElement('div#site-header-menu > nav#main-header');

The final statement cannot find the nav#main-header element.
As I approach the code in the header.php file of the Twentysixteen theme I see that the markup defining the menu I’m targeting has an id attribute specified already; not willing to violate HTML validation I modify the test to target a class attribute in place of the id one

// ...all of the above

$I->amOnPage('/');
$I->seeElement('div#site-header-menu > nav.main-navigation');
$I->seeElement('div#site-header-menu > nav.main-header');

and run the acceptance test again expecting it to fail
Failing on class too
The test is still failing so it’s time to modify the header.php code.

Copy and paste job

The theme is child to the Twentysixteen one hence “modifying the header file” means copying the header.php file over in the _blogs theme folder and change the lines that generate the primary menu markup code, so I go from this

<?php if ( has_nav_menu( 'primary' ) ) : ?>
    <nav id="site-navigation" class="main-navigation" role="navigation" aria-label="<?php _e( 'Primary Menu', 'twentysixteen' ); ?>">
        <?php
        wp_nav_menu( array(
            'theme_location' => 'primary',
            'menu_class'     => 'primary-menu',
        ) );
        ?>
    </nav><!-- .main-navigation -->
<?php endif; ?>

to this

<?php if ( has_nav_menu( 'primary' ) ) : ?>
    <nav id="site-navigation" class="main-navigation <?php _blogs_primary_menu_classes(); ?>" role="navigation" aria-label="<?php _e( 'Primary Menu', 'twentysixteen' ); ?>">
        <?php
        wp_nav_menu( array(
            'theme_location' => 'primary',
            'menu_class'     => 'primary-menu',
        ) );
        ?>
    </nav><!-- .main-navigation -->
<?php endif; ?>

The function I define in the theme functions.php file

function _blogs_primary_menu_classes() {
    echo 'main-header';
}

I’m not, at this point, considering the multisite support and am focusing only on making this first test pass.
Passing on class

Another failing test

Since this first test is passing it’s time to write another one that should fail, on to the second story

Given WordPress is installed as single site
And there is a menu registered in the primary location
When I visit the main site index page
Then I should see a div#site-header-menu > nav.main-header element.

and in a Codeception Cept test case code it translates to

$I = new AcceptanceTester( $scenario );
$I->wantTo( 'see the main-header id on the main site header on a multi site' );

// setup multisite installation
$I->haveMultisiteInDatabase( true, true );
$I->useMainBlog();

// set the theme to `_blogs`
$I->haveOptionInDatabase( 'template', 'Twentysixteen' );
$I->haveOptionInDatabase( 'stylesheet', '_blogs' );
$I->haveOptionInDatabase( 'current_theme', '_Blogs' );

// add a nav menu
$menu_id = $I->haveTermInDatabase( 'Menu 1', 'nav_menu', [ 'slug' => 'menu1' ] );

// set theme options to use the `primary` location
$I->haveOptionInDatabase( 'theme_mods__blogs', [ 'nav_menu_locations' => [ 'primary' => $menu_id ] ] );

// add one element to the menu
$menu_item_id = $I->havePostInDatabase( [
    'post_title' => 'theAverageDev',
    'menu_order' => 1,
    'post_type'  => 'nav_menu_item'
] );
$meta         = [
    '_menu_item_type'             => 'custom',
    '_menu_item_object_id'        => $menu_item_id,
    '_menu_item_object'           => 'custom',
    '_menu_item_url'              => 'http://theaveragedev.com'
];
foreach ( $meta as $key => $value ) {
    $I->havePostmetaInDatabase( $menu_item_id, $key, $value );
}

$I->amOnPage('/');
$I->seeElement('div#site-header-menu > nav.main-navigation');
$I->seeElement('div#site-header-menu > nav.main-header');

Beside the first lines of code that are in charge of setting up the multisite installation little has changed and the test, not surprisingly, is passing.
Unexpectedly passing mu
Why? A look at the code of the _blogs_primary_menu_classes function tells me it’s not taking the multisite setting into account, no calls to the is_multisite function, and will output the right class on the main blog header.

On GitHub

The code is on GitHub and current to this post.

Next

I appreciate your input