SelectOrOtherTestBase.test in Select (or other) 7.3
Contains SelectOrOtherTestBase.
File
tests/SelectOrOtherTestBase.testView source
<?php
/**
* @file
* Contains SelectOrOtherTestBase.
*/
/**
* Class SelectOrOtherTestBase
* Base class for select_or_other testing.
*/
class SelectOrOtherTestBase extends DrupalWebTestCase {
protected $defaultPermissions;
/**
* @var array $fields
* associated array keyed by field_name with the following information:
* - Widget (machine name of the widget used)
* - Cardinality (1, -1)
* - field_settings @see field_info_field().
* - instance_settings @see field_info_instance().
*
*/
protected $fields;
public function setUp() {
// Also enable any modules required by the tests overriding this base class.
$modules = func_get_args();
if (isset($modules[0]) && is_array($modules[0])) {
$modules = $modules[0];
}
// At the very least enable the select_or_other module.
parent::setUp(array_merge(array(
'select_or_other',
), $modules));
// Clear the array of fields to test.
$this->fields = array();
}
/**
* Check to see if a label is visible only once.
* @param string $label
* The label to look for.
* @param string $element_name
* The element the label should be for.
*/
protected function assertLabelVisibleOnce($label, $element_name) {
$xpath = "//label[@for[starts-with(., :element-name)] and starts-with(., :label)]";
$arguments = array(
':label' => $label,
':element-name' => $element_name,
);
$message_arguments = array(
'%label' => $label,
'%element-name' => $element_name,
);
$elements = $this
->xpath($xpath, $arguments);
$this
->assertEqual(count($elements), 1, t('%label is visible once for element %element', $message_arguments));
}
/**
* Make sure the field label is visible only once.
*/
function testFieldLabelVisibleOnce() {
foreach ($this->fields as $field_name => $field) {
$this
->drupalGet('node/add/' . $this
->getFieldContentType($field_name));
$this
->assertLabelVisibleOnce($field_name, "edit-{$field_name}-und-select");
}
}
/**
* Make sure field cardinality is checked.
*/
function testCardinalityValidation() {
$tested_types = array();
foreach ($this->fields as $field_name => $field) {
$widget_type = $field['instance_settings']['widget']['type'];
if (!isset($tested_types[$widget_type])) {
$field_info = field_info_field($field_name);
$field_info['cardinality'] = $this->fields[$field_name]['cardinality'] = 2;
field_update_field($field_info);
$this
->selectAllOptions($field_name);
$this
->assertText('cannot hold more than 2 values');
$tested_types[$widget_type] = TRUE;
}
}
}
/**
* Make sure an empty option is present when relevant.
*/
function testEmptyOption($other_option = '') {
foreach ($this->fields as $field_name => $field) {
$this
->drupalGet('node/add/' . $this
->getFieldContentType($field_name));
$type = $this
->getWidgetType($field_name);
$multiple = $field['cardinality'] !== 1;
$required = $field['instance_settings']['required'];
// First test empty behaviour. Only single select boxes should always have
// an empty value.
if ($type === 'select' && !$multiple) {
if ($required) {
$this
->assertText(t('- Select -'));
}
else {
$this
->assertText(t('- None -'));
}
}
else {
$this
->assertNoText(t('- Select -'));
$this
->assertNoText(t('- None -'));
}
// Test non-empty behaviour. Once again only single cardinality elements
// should have empty options to allow for the removal of values if the
// field is not required.
if ($other_option !== '') {
// We set the other option, because we can set that in the same way
// always.
$this
->setFieldValue($field_name, 'select_or_other', $other_option);
$this
->clickLink(t('Edit'));
if (!$multiple && !$required) {
$this
->assertText(t('- None -'));
}
else {
$this
->assertNoText(t('- Select -'));
$this
->assertNoText(t('- None -'));
}
}
else {
$this
->fail('No $other_option provided, this test should be overridden and calling itself from individual test classes.');
}
}
}
/**
* Generate content types and fields for testing.
* @param string $field_type
* The type of field to create.
* @param array $widgets
* The types of widgets to use.
* @param array $widget_settings
* The widget settings.
* @param $field_formatter
* Machine name of the field formatter to use for display.
* @throws \Exception
* @throws \FieldException
*/
protected function prepareTestFields($field_type, $field_settings, $widgets, $widget_settings, $field_formatter) {
// Configure fields.
foreach ($widgets as $widget) {
foreach (array(
1,
-1,
) as $cardinality) {
foreach (array(
TRUE,
FALSE,
) as $required) {
$content_type = $this
->drupalCreateContentType();
$field_info = array(
'content_type' => $content_type,
'widget' => $widget,
'cardinality' => $cardinality,
);
// Create the field.
$field = array(
'type' => $field_type,
'field_name' => strtolower($this
->randomName()),
'cardinality' => $cardinality,
'settings' => $field_settings,
);
field_create_field($field);
$field_info['field_settings'] = $field;
$instance_settings = array(
'entity_type' => 'node',
'required' => $required,
'bundle' => $field_info['content_type']->name,
'field_name' => $field['field_name'],
'widget' => array(
'type' => $widget,
'settings' => $widget_settings,
),
'display' => array(
'full' => array(
'type' => $field_formatter,
),
),
);
$field_info['instance_settings'] = field_create_instance($instance_settings);
$this->fields[$field['field_name']] = $field_info;
}
}
}
// Determine required permissions.
$this->defaultPermissions = array(
'bypass node access',
);
}
/**
* Submit the add node form with the selected values.
* @param $field_name
* @param $select
* @param $other
*/
protected function setFieldValue($field_name, $select, $other = '') {
$edit = array();
// A node requires a title.
$edit["title"] = $this
->randomName(8);
$this
->drupalGet('node/add/' . $this
->getFieldContentType($field_name));
// Set the select value.
if ($this->fields[$field_name]['cardinality'] == 1) {
$edit["{$field_name}[und][select]"] = $select;
}
else {
// We have to treat multiple selection elements differently.
if ($this
->getWidgetType($field_name) === 'select') {
// We're dealing with a multiple select.
$edit["{$field_name}[und][select][]"] = $select;
}
else {
// We're dealing with checkboxes.
$edit["{$field_name}[und][select][{$select}]"] = $select;
}
}
// Set the other value.
$edit["{$field_name}[und][other]"] = $other;
// Create the node.
$this
->drupalPost(NULL, $edit, t('Save'));
}
/**
* Submit the add node form with all options selected for the specified field.
*
* @param string $field_name
* Name of the field to select all options for.
* @param string $other_option
* Optionally provide a value for the other field. Will default to 999
*/
protected function selectAllOptions($field_name, $other_option = '') {
$edit = array();
// A node requires a title.
$edit["title"] = $this
->randomName(8);
$this
->drupalGet('node/add/' . $this
->getFieldContentType($field_name));
// Set the select value.
if ($this->fields[$field_name]['cardinality'] == 1) {
$this
->fail('Unable to select multiple options because the cardinality is 1');
}
else {
// We have to treat multiple selection elements differently.
if ($this
->getWidgetType($field_name) === 'select') {
// Select all options for this select box.
$xpath = "//select[@id = :id]/option";
$arguments = array(
':id' => "edit-{$field_name}-und-select",
);
$options = $this
->xpath($xpath, $arguments);
// Prepare array of values.
$select = array();
foreach ($options as $option) {
$select[] = $option['value'];
}
$edit["{$field_name}[und][select][]"] = $select;
}
else {
// Find all checkboxes.
$xpath = "//input[@id[starts-with(., :id)]]";
$arguments = array(
':id' => "edit-{$field_name}-und-select",
);
$options = $this
->xpath($xpath, $arguments);
foreach ($options as $option) {
$id = reset($option['id']);
$label = $this
->xpath('//label[@for = :id]', array(
':id' => $id,
));
$key = reset($option['name']);
$value = (string) reset($label);
$edit[$key] = trim($value);
}
}
}
// Unless the other option is overridden, set a numeric other value because
// each widget will accept one.
$edit["{$field_name}[und][other]"] = $other_option == '' ? 999 : $other_option;
// Create the node.
$this
->drupalPost(NULL, $edit, t('Save'));
}
/**
* Determines the type of widget used on the page.
*
* @param string $field_name
* The field name to determine widget type for.
* @return string
* 'select' or 'buttons' depending on the widget type.
*/
protected function getWidgetType($field_name) {
$xpath = "//select[@id = :id]";
$arguments = array(
':id' => "edit-{$field_name}-und-select",
);
$elements = $this
->xpath($xpath, $arguments);
// we are dealing with a select widget.
if (count($elements)) {
return 'select';
}
else {
return 'buttons';
}
}
/**
* Returns the machine name of the content type a field is configured on.
*
* @param $field_name
* The field machine name of which to retrieve the content type.
* @return string|null
* The content type machine name or NULL if not found.
*/
protected function getFieldContentType($field_name) {
return $this->fields[$field_name]['content_type']->name;
}
}
Classes
Name | Description |
---|---|
SelectOrOtherTestBase | Class SelectOrOtherTestBase Base class for select_or_other testing. |