1 layout.test LayoutInterfaceTest::testContexts()

Test the support for contexts within conditions and blocks.

File

core/modules/layout/tests/layout.test, line 590
Tests for the Layout module.

Class

LayoutInterfaceTest
Tests the interface for adding, removing, and moving blocks.

Code

function testContexts() {
  // Make a new layout that creates a custom path with wildcards.
  $layout_title = $this->randomName();
  $layout_name = strtolower($layout_title);
  $layout_path = 'node/%/foo/%';
  $edit = array(
    'title' => $layout_title,
    'name' => $layout_name,
    'layout_template' => 'moscone_flipped',
    'path' => $layout_path,
  );
  // Check the path first to populate available contexts.
  $this->backdropPost('admin/structure/layouts/add', $edit, t('Check path'));

  // The first context (node) should be auto-detected and not require a value.
  $edit = array(
    'context[required][3][plugin]' => 'user',
  );
  $this->backdropPost('admin/structure/layouts/add', $edit, t('Create layout'));

  // Add the test block that requires both node and user contexts.
  $this->clickLink(t('Add block'), 2);
  $this->assertText(t('A testing block for layouts with contexts.'));
  $this->clickLink(t('Layout bar block'));

  $this->assertNoField('contexts[my_node]', 'Node context selector not shown, only a single option.');
  $this->assertField('contexts[my_user]', 'User context selector is shown.');
  $this->backdropPost(NULL, array(), t('Add block'));

  // Record the UUID for the newly added block.
  $last_block = $this->xpath('(//*[@id="layout-content-form"]//*[contains(@class,:region)]//*[@data-block-id])[last()]', array(
    ':region' => 'l-content',
  ));
  $block_uuid = (string) $last_block[0]['data-block-id'];
  $block_edit_url = 'admin/structure/layouts/manage/' . $layout_name . '/configure-block/editor/' . $block_uuid;

  $this->backdropPost(NULL, array(), t('Save layout'));

  $this->backdropGet('node/' . $this->test_node1->nid . '/foo/' . $this->web_user->uid);
  $this->assertText(format_string('The user name is @name and the node title is @title', array('@name' => $this->web_user->name, '@title' => $this->test_node1->title)));

  // Modify the layout path to remove "node/", removing the auto-selection.
  $edit = array(
    'path' => 'foo/%/bar/%',
  );
  $this->backdropPost('admin/structure/layouts/manage/' . $layout_name . '/configure', $edit, t('Check path'));
  $edit = array(
    'context[required][1][plugin]' => 'node',
  );
  $this->backdropPost(NULL, $edit, t('Save layout'));

  // Check that the block still works, even with the contexts changed.
  $this->backdropGet('foo/' . $this->test_node1->nid . '/bar/' . $this->web_user->uid);
  $this->assertText(format_string('The user name is @name and the node title is @title', array('@name' => $this->web_user->name, '@title' => $this->test_node1->title)));

  // Change the second context to be a node context. The user context should
  // still work, as it will use the current user context.
  $edit = array(
    'context[required][3][plugin]' => 'node',
  );
  $this->backdropPost('admin/structure/layouts/manage/' . $layout_name . '/configure', $edit, t('Save layout'));

  // Now the page should show the current user instead of the one in the URL.
  $this->backdropGet('foo/' . $this->test_node1->nid . '/bar/' . $this->test_node2->nid);
  $this->assertText(format_string('The user name is @name and the node title is @title', array('@name' => $this->admin_user->name, '@title' => $this->test_node1->title)));

  // Change the "my_node" context to use the argument in position 3 instead
  // of position 1.
  $this->backdropGet($block_edit_url);
  $this->assertField('contexts[my_node]', 'Node context selector is shown.');
  $this->assertNoField('contexts[my_user]', 'User context selector is not shown, only the current user available.');

  $edit = array(
    'contexts[my_node]' => '3',
  );
  $this->backdropPost(NULL, $edit, t('Update block'));
  $this->backdropPost(NULL, array(), t('Save layout'));

  // Now the second node should be used as the title in the page.
  $this->backdropGet('foo/' . $this->test_node1->nid . '/bar/' . $this->test_node2->nid);
  $this->assertText(format_string('The user name is @name and the node title is @title', array('@name' => $this->admin_user->name, '@title' => $this->test_node2->title)));

  // Delete the layout to prevent it interfering with following tests.
  $this->backdropPost('admin/structure/layouts/manage/' . $layout_name . '/delete', array(), t('Delete layout'));

  // Make a new layout that creates a custom path with a string pass-through.
  $layout_title = $this->randomName();
  $layout_name = strtolower($layout_title);
  $layout_path = 'passthrough/%';
  $edit = array(
    'title' => $layout_title,
    'name' => $layout_name,
    'layout_template' => 'boxton',
    'path' => $layout_path,
  );
  // Create with the default context (string pass-through).
  $this->backdropPost('admin/structure/layouts/add', $edit, t('Create layout'));

  // Add the test block that requires both node and user contexts.
  $this->clickLink(t('Add block'), 2);
  $this->clickLink(t('String pass-through test'));
  $this->backdropPost(NULL, array(), t('Add block'));
  $this->backdropPost(NULL, array(), t('Save layout'));

  $argument_string = 'argument-value-from-url';
  $this->backdropGet('passthrough/' . $argument_string);
  $this->assertText(format_string('The page argument is @string', array('@string' => $argument_string)));

  // Test custom contexts.
  // Make a new layout with a random path.
  $layout_title = $this->randomName();
  $layout_name = strtolower($layout_title);
  $layout_path = $layout_name;
  $edit = array(
    'title' => $layout_title,
    'name' => $layout_name,
    'layout_template' => 'moscone_flipped',
    'path' => $layout_path,
  );
  // Check the path first to populate available contexts.
  $this->backdropPost('admin/structure/layouts/add', $edit, t('Check path'));

  $this->assertNoText(t('Node ID: 1'));
  $this->assertNoText(t('Node ID: 2'));
  $this->assertNoText(t('User account ID: 3'));

  $this->backdropPost('admin/structure/layouts/add', array(), t('Create layout'));

  // Check that the test block that requires both node and user contexts is
  // not available.
  $this->clickLink(t('Add block'), 2);
  $this->assertNoText(t('A testing block for layouts with contexts.'));

  // Test custom context validation.
  $edit = array();
  $this->backdropPost('admin/structure/layouts/manage/' . $layout_name . '/configure', $edit, t('Add context'));

  // Add a custom node context to the layout.
  $edit = array(
    'context' => 'node',
  );
  $this->backdropPost(NULL, $edit, t('Load context'));
  $edit = array(
    'id' => '2',
  );
  $this->backdropPost(NULL, $edit, t('Add context'));

  $this->assertNoText(t('Node ID: 1'));
  $this->assertText(t('Node ID: 2'));
  $this->assertNoText(t('User account ID: 3'));

  // Test configuring custom contexts.
  // Saving a File context will fail since no files have been created yet.
  $this->backdropPost(NULL, array(), t('Configure'));
  $edit = array(
    'context' => 'file',
  );
  $this->backdropPost(NULL, $edit, t('Load context'));
  $edit = array(
    'id' => '1',
  );
  $this->backdropPost(NULL, $edit, t('Save context'));
  $error_message = t('The selected File does not exist.');
  $this->assertRaw($error_message);
  $edit = array(
    'id' => '',
  );
  $this->backdropPost(NULL, $edit, t('Save context'));
  $error_message = t('An ID is required.');
  $this->assertRaw($error_message);
  $this->backdropPost(NULL, $edit, t('Cancel'));

  $this->backdropPost(NULL, array(), t('Remove'));

  $this->assertNoText(t('Node ID: 1'));
  $this->assertNoText(t('Node ID: 2'));
  $this->assertNoText(t('User account ID: 3'));

  // Add a custom node context to the layout.
  $this->backdropPost(NULL, array(), t('Add context'));
  $edit = array(
    'context' => 'node',
  );
  $this->backdropPost(NULL, $edit, t('Load context'));
  $edit = array(
    'id' => '1',
  );
  $this->backdropPost(NULL, $edit, t('Add context'));

  $this->assertText(t('Node ID: 1'));
  $this->assertNoText(t('Node ID: 2'));
  $this->assertNoText(t('User account ID: 3'));

  $this->backdropPost(NULL, array(), t('Save layout'));

  // Check that the test block that requires both node and user contexts is
  // now available.
  $this->clickLink(t('Add block'), 2);
  $this->assertText(t('A testing block for layouts with contexts.'));
  $this->clickLink(t('Layout bar block'));

  $this->assertNoField('contexts[my_node]', 'Node context selector not shown, only a single option.');
  $this->assertNoField('contexts[my_user]', 'User context selector is not shown.');
  $this->backdropPost(NULL, array(), t('Add block'));

  // Record the UUID for the newly added block.
  $last_block = $this->xpath('(//*[@id="layout-content-form"]//*[contains(@class,:region)]//*[@data-block-id])[last()]', array(
    ':region' => 'l-content',
  ));
  $block_uuid = (string) $last_block[0]['data-block-id'];
  $block_edit_url = 'admin/structure/layouts/manage/' . $layout_name . '/configure-block/editor/' . $block_uuid;

  $this->backdropPost(NULL, array(), t('Save layout'));

  $this->backdropGet($layout_path);
  $this->assertText(format_string('The user name is @name and the node title is @title', array('@name' => $this->admin_user->name, '@title' => $this->test_node1->title)));

  // Add another custom node context to the layout.
  $edit = array();
  $this->backdropPost('admin/structure/layouts/manage/' . $layout_name . '/configure', $edit, t('Add context'));
  $edit = array(
    'context' => 'node',
  );
  $this->backdropPost(NULL, $edit, t('Load context'));
  $edit = array(
    'id' => '2',
  );
  $this->backdropPost(NULL, $edit, t('Add context'));

  $this->assertText(t('Node ID: 1'));
  $this->assertText(t('Node ID: 2'));
  $this->assertNoText(t('User account ID: 3'));

  $this->backdropPost(NULL, array(), t('Save layout'));

  $this->backdropGet($block_edit_url);
  $this->assertField('contexts[my_node]', 'Node context selector is shown.');
  $this->assertNoField('contexts[my_user]', 'User context selector is not shown, only the current user available.');

  $edit = array(
    'contexts[my_node]' => 'node2',
  );
  $this->backdropPost(NULL, $edit, t('Update block'));
  $this->backdropPost(NULL, array(), t('Save layout'));

  // Now the second node should be used as the title in the page.
  $this->backdropGet($layout_path);
  $this->assertText(format_string('The user name is @name and the node title is @title', array('@name' => $this->admin_user->name, '@title' => $this->test_node2->title)));

  // Add a custom user context to the layout.
  $edit = array();
  $this->backdropPost('admin/structure/layouts/manage/' . $layout_name . '/configure', $edit, t('Add context'));
  $edit = array(
    'context' => 'user',
  );
  $this->backdropPost(NULL, $edit, t('Load context'));
  $edit = array(
    'id' => $this->web_user->uid,
  );
  $this->backdropPost(NULL, $edit, t('Add context'));

  $this->assertText(t('Node ID: 1'));
  $this->assertText(t('Node ID: 2'));
  $this->assertText(t('User account ID: 3'));

  $this->backdropPost(NULL, array(), t('Save layout'));

  $this->backdropGet($block_edit_url);
  $this->assertField('contexts[my_node]', 'Node context selector is shown.');
  $this->assertField('contexts[my_user]', 'User context selector is shown.');

  $edit = array(
    'contexts[my_user]' => 'user3',
  );
  $this->backdropPost(NULL, $edit, t('Update block'));
  $this->backdropPost(NULL, array(), t('Save layout'));

  // Now the web user's name should be used as the title in the page.
  $this->backdropGet($layout_path);
  $this->assertText(format_string('The user name is @name and the node title is @title', array('@name' => $this->web_user->name, '@title' => $this->test_node2->title)));

  // Test that custom layouts and path layouts work together.
  $layout_title = $this->randomName();
  $layout_name = strtolower($layout_title);
  $layout_path = 'node/%';
  $edit = array(
    'title' => $layout_title,
    'name' => $layout_name,
    'layout_template' => 'moscone_flipped',
    'path' => $layout_path,
  );
  // Check the path first to populate available contexts.
  $this->backdropPost('admin/structure/layouts/add', $edit, t('Check path'));

  $this->assertNoText(t('Node ID: 1'));
  $this->backdropPost('admin/structure/layouts/add', array(), t('Create layout'));

  // Add a custom node context to the layout.
  $edit = array();
  $this->backdropPost('admin/structure/layouts/manage/' . $layout_name . '/configure', $edit, t('Add context'));
  $edit = array(
    'context' => 'node',
  );
  $this->backdropPost(NULL, $edit, t('Load context'));
  $edit = array(
    'id' => '2',
  );
  $this->backdropPost(NULL, $edit, t('Add context'));

  $this->assertText(t('Position 2: node/%'));
  $this->assertText(t('Node ID: 2'));
  $this->backdropPost(NULL, array(), t('Save layout'));

  // Check that the test block that requires both node and user contexts is
  // now available.
  $this->clickLink(t('Add block'), 2);
  $this->assertText(t('A testing block for layouts with contexts.'));
  $this->clickLink(t('Layout bar block'));

  $this->assertField('contexts[my_node]', 'Node context selector shown.');

  $edit = array(
    'contexts[my_node]' => 'node2',
  );
  $this->backdropPost(NULL, array(), t('Add block'));

  $this->backdropPost(NULL, array(), t('Save layout'));

  // Go to a node path and check that the block shows with the correct
  // content.
  $this->backdropGet('node/' . $this->test_node1->nid);
  $this->assertText(format_string('The user name is @name and the node title is @title', array('@name' => $this->admin_user->name, '@title' => $this->test_node2->title)));

}