Chris@0: drupalCreateUser(['access content', 'administer taxonomy', 'access administration pages', 'administer site configuration', 'administer content types', 'administer nodes', 'bypass node access', 'administer node fields', 'administer node display']); Chris@0: $this->drupalLogin($admin_user); Chris@0: Chris@0: // Create content type, with underscores. Chris@0: $this->typeName = 'test_' . strtolower($this->randomMachineName()); Chris@0: $type = $this->drupalCreateContentType(['name' => $this->typeName, 'type' => $this->typeName]); Chris@0: $this->type = $type->id(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Options (integer) : test 'allowed values' input. Chris@0: */ Chris@0: public function testOptionsAllowedValuesInteger() { Chris@0: $this->fieldName = 'field_options_integer'; Chris@0: $this->createOptionsField('list_integer'); Chris@0: Chris@0: // Flat list of textual values. Chris@0: $string = "Zero\nOne"; Chris@0: $array = ['0' => 'Zero', '1' => 'One']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are accepted.'); Chris@0: // Explicit integer keys. Chris@0: $string = "0|Zero\n2|Two"; Chris@0: $array = ['0' => 'Zero', '2' => 'Two']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Integer keys are accepted.'); Chris@0: // Check that values can be added and removed. Chris@0: $string = "0|Zero\n1|One"; Chris@0: $array = ['0' => 'Zero', '1' => 'One']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Values can be added and removed.'); Chris@0: // Non-integer keys. Chris@0: $this->assertAllowedValuesInput("1.1|One", 'keys must be integers', 'Non integer keys are rejected.'); Chris@0: $this->assertAllowedValuesInput("abc|abc", 'keys must be integers', 'Non integer keys are rejected.'); Chris@0: // Mixed list of keyed and unkeyed values. Chris@0: $this->assertAllowedValuesInput("Zero\n1|One", 'invalid input', 'Mixed lists are rejected.'); Chris@0: Chris@0: // Create a node with actual data for the field. Chris@0: $settings = [ Chris@0: 'type' => $this->type, Chris@0: $this->fieldName => [['value' => 1]], Chris@0: ]; Chris@0: $node = $this->drupalCreateNode($settings); Chris@0: Chris@0: // Check that a flat list of values is rejected once the field has data. Chris@0: $this->assertAllowedValuesInput("Zero\nOne", 'invalid input', 'Unkeyed lists are rejected once the field has data.'); Chris@0: Chris@0: // Check that values can be added but values in use cannot be removed. Chris@0: $string = "0|Zero\n1|One\n2|Two"; Chris@0: $array = ['0' => 'Zero', '1' => 'One', '2' => 'Two']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Values can be added.'); Chris@0: $string = "0|Zero\n1|One"; Chris@0: $array = ['0' => 'Zero', '1' => 'One']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.'); Chris@0: $this->assertAllowedValuesInput("0|Zero", 'some values are being removed while currently in use', 'Values in use cannot be removed.'); Chris@0: Chris@0: // Delete the node, remove the value. Chris@0: $node->delete(); Chris@0: $string = "0|Zero"; Chris@0: $array = ['0' => 'Zero']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.'); Chris@0: Chris@0: // Check that the same key can only be used once. Chris@0: $string = "0|Zero\n0|One"; Chris@0: $array = ['0' => 'One']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Same value cannot be used multiple times.'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Options (float) : test 'allowed values' input. Chris@0: */ Chris@0: public function testOptionsAllowedValuesFloat() { Chris@0: $this->fieldName = 'field_options_float'; Chris@0: $this->createOptionsField('list_float'); Chris@0: Chris@0: // Flat list of textual values. Chris@0: $string = "Zero\nOne"; Chris@0: $array = ['0' => 'Zero', '1' => 'One']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are accepted.'); Chris@0: // Explicit numeric keys. Chris@0: $string = "0|Zero\n.5|Point five"; Chris@0: $array = ['0' => 'Zero', '0.5' => 'Point five']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Integer keys are accepted.'); Chris@0: // Check that values can be added and removed. Chris@0: $string = "0|Zero\n.5|Point five\n1.0|One"; Chris@0: $array = ['0' => 'Zero', '0.5' => 'Point five', '1' => 'One']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Values can be added and removed.'); Chris@0: // Non-numeric keys. Chris@0: $this->assertAllowedValuesInput("abc|abc\n", 'each key must be a valid integer or decimal', 'Non numeric keys are rejected.'); Chris@0: // Mixed list of keyed and unkeyed values. Chris@0: $this->assertAllowedValuesInput("Zero\n1|One\n", 'invalid input', 'Mixed lists are rejected.'); Chris@0: Chris@0: // Create a node with actual data for the field. Chris@0: $settings = [ Chris@0: 'type' => $this->type, Chris@0: $this->fieldName => [['value' => .5]], Chris@0: ]; Chris@0: $node = $this->drupalCreateNode($settings); Chris@0: Chris@0: // Check that a flat list of values is rejected once the field has data. Chris@0: $this->assertAllowedValuesInput("Zero\nOne", 'invalid input', 'Unkeyed lists are rejected once the field has data.'); Chris@0: Chris@0: // Check that values can be added but values in use cannot be removed. Chris@0: $string = "0|Zero\n.5|Point five\n2|Two"; Chris@0: $array = ['0' => 'Zero', '0.5' => 'Point five', '2' => 'Two']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Values can be added.'); Chris@0: $string = "0|Zero\n.5|Point five"; Chris@0: $array = ['0' => 'Zero', '0.5' => 'Point five']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.'); Chris@0: $this->assertAllowedValuesInput("0|Zero", 'some values are being removed while currently in use', 'Values in use cannot be removed.'); Chris@0: Chris@0: // Delete the node, remove the value. Chris@0: $node->delete(); Chris@0: $string = "0|Zero"; Chris@0: $array = ['0' => 'Zero']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.'); Chris@0: Chris@0: // Check that the same key can only be used once. Chris@0: $string = "0.5|Point five\n0.5|Half"; Chris@0: $array = ['0.5' => 'Half']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Same value cannot be used multiple times.'); Chris@0: Chris@0: // Check that different forms of the same float value cannot be used. Chris@0: $string = "0|Zero\n.5|Point five\n0.5|Half"; Chris@0: $array = ['0' => 'Zero', '0.5' => 'Half']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Different forms of the same value cannot be used.'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Options (text) : test 'allowed values' input. Chris@0: */ Chris@0: public function testOptionsAllowedValuesText() { Chris@0: $this->fieldName = 'field_options_text'; Chris@0: $this->createOptionsField('list_string'); Chris@0: Chris@0: // Flat list of textual values. Chris@0: $string = "Zero\nOne"; Chris@0: $array = ['Zero' => 'Zero', 'One' => 'One']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are accepted.'); Chris@0: // Explicit keys. Chris@0: $string = "zero|Zero\none|One"; Chris@0: $array = ['zero' => 'Zero', 'one' => 'One']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Explicit keys are accepted.'); Chris@0: // Check that values can be added and removed. Chris@0: $string = "zero|Zero\ntwo|Two"; Chris@0: $array = ['zero' => 'Zero', 'two' => 'Two']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Values can be added and removed.'); Chris@0: // Mixed list of keyed and unkeyed values. Chris@0: $string = "zero|Zero\nOne\n"; Chris@0: $array = ['zero' => 'Zero', 'One' => 'One']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Mixed lists are accepted.'); Chris@0: // Overly long keys. Chris@0: $this->assertAllowedValuesInput("zero|Zero\n" . $this->randomMachineName(256) . "|One", 'each key must be a string at most 255 characters long', 'Overly long keys are rejected.'); Chris@0: Chris@0: // Create a node with actual data for the field. Chris@0: $settings = [ Chris@0: 'type' => $this->type, Chris@0: $this->fieldName => [['value' => 'One']], Chris@0: ]; Chris@0: $node = $this->drupalCreateNode($settings); Chris@0: Chris@0: // Check that flat lists of values are still accepted once the field has Chris@0: // data. Chris@0: $string = "Zero\nOne"; Chris@0: $array = ['Zero' => 'Zero', 'One' => 'One']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are still accepted once the field has data.'); Chris@0: Chris@0: // Check that values can be added but values in use cannot be removed. Chris@0: $string = "Zero\nOne\nTwo"; Chris@0: $array = ['Zero' => 'Zero', 'One' => 'One', 'Two' => 'Two']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Values can be added.'); Chris@0: $string = "Zero\nOne"; Chris@0: $array = ['Zero' => 'Zero', 'One' => 'One']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.'); Chris@0: $this->assertAllowedValuesInput("Zero", 'some values are being removed while currently in use', 'Values in use cannot be removed.'); Chris@0: Chris@0: // Delete the node, remove the value. Chris@0: $node->delete(); Chris@0: $string = "Zero"; Chris@0: $array = ['Zero' => 'Zero']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.'); Chris@0: Chris@0: // Check that string values with dots can be used. Chris@0: $string = "Zero\nexample.com|Example"; Chris@0: $array = ['Zero' => 'Zero', 'example.com' => 'Example']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'String value with dot is supported.'); Chris@0: Chris@0: // Check that the same key can only be used once. Chris@0: $string = "zero|Zero\nzero|One"; Chris@0: $array = ['zero' => 'One']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Same value cannot be used multiple times.'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Options (text) : test 'trimmed values' input. Chris@0: */ Chris@0: public function testOptionsTrimmedValuesText() { Chris@0: $this->fieldName = 'field_options_trimmed_text'; Chris@0: $this->createOptionsField('list_string'); Chris@0: Chris@0: // Explicit keys. Chris@0: $string = "zero |Zero\none | One"; Chris@0: $array = ['zero' => 'Zero', 'one' => 'One']; Chris@0: $this->assertAllowedValuesInput($string, $array, 'Explicit keys are accepted and trimmed.'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Helper function to create list field of a given type. Chris@0: * Chris@0: * @param string $type Chris@0: * One of 'list_integer', 'list_float' or 'list_string'. Chris@0: */ Chris@0: protected function createOptionsField($type) { Chris@0: // Create a field. Chris@0: FieldStorageConfig::create([ Chris@0: 'field_name' => $this->fieldName, Chris@0: 'entity_type' => 'node', Chris@0: 'type' => $type, Chris@0: ])->save(); Chris@0: FieldConfig::create([ Chris@0: 'field_name' => $this->fieldName, Chris@0: 'entity_type' => 'node', Chris@0: 'bundle' => $this->type, Chris@0: ])->save(); Chris@0: Chris@0: entity_get_form_display('node', $this->type, 'default')->setComponent($this->fieldName)->save(); Chris@0: Chris@0: $this->adminPath = 'admin/structure/types/manage/' . $this->type . '/fields/node.' . $this->type . '.' . $this->fieldName . '/storage'; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests a string input for the 'allowed values' form element. Chris@0: * Chris@0: * @param $input_string Chris@0: * The input string, in the pipe-linefeed format expected by the form Chris@0: * element. Chris@0: * @param $result Chris@0: * Either an expected resulting array in Chris@0: * $field->getSetting('allowed_values'), or an expected error message. Chris@0: * @param $message Chris@0: * Message to display. Chris@0: */ Chris@0: public function assertAllowedValuesInput($input_string, $result, $message) { Chris@0: $edit = ['settings[allowed_values]' => $input_string]; Chris@0: $this->drupalPostForm($this->adminPath, $edit, t('Save field settings')); Chris@0: $this->assertNoRaw('<', 'The page does not have double escaped HTML tags.'); Chris@0: Chris@0: if (is_string($result)) { Chris@0: $this->assertText($result, $message); Chris@0: } Chris@0: else { Chris@0: $field_storage = FieldStorageConfig::loadByName('node', $this->fieldName); Chris@0: $this->assertIdentical($field_storage->getSetting('allowed_values'), $result, $message); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests normal and key formatter display on node display. Chris@0: */ Chris@0: public function testNodeDisplay() { Chris@0: $this->fieldName = strtolower($this->randomMachineName()); Chris@0: $this->createOptionsField('list_integer'); Chris@0: $node = $this->drupalCreateNode(['type' => $this->type]); Chris@0: Chris@0: $on = $this->randomMachineName(); Chris@0: $off = $this->randomMachineName(); Chris@0: $edit = [ Chris@0: 'settings[allowed_values]' => Chris@0: "1|$on Chris@0: 0|$off", Chris@0: ]; Chris@0: Chris@0: $this->drupalPostForm($this->adminPath, $edit, t('Save field settings')); Chris@0: $this->assertText(format_string('Updated field @field_name field settings.', ['@field_name' => $this->fieldName]), "The 'On' and 'Off' form fields work for boolean fields."); Chris@0: Chris@0: // Select a default value. Chris@0: $edit = [ Chris@0: $this->fieldName => '1', Chris@0: ]; Chris@0: $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); Chris@0: Chris@0: // Check the node page and see if the values are correct. Chris@0: $file_formatters = ['list_default', 'list_key']; Chris@0: foreach ($file_formatters as $formatter) { Chris@0: $edit = [ Chris@0: "fields[$this->fieldName][type]" => $formatter, Chris@0: "fields[$this->fieldName][region]" => 'content', Chris@0: ]; Chris@0: $this->drupalPostForm('admin/structure/types/manage/' . $this->typeName . '/display', $edit, t('Save')); Chris@0: $this->drupalGet('node/' . $node->id()); Chris@0: Chris@0: if ($formatter == 'list_default') { Chris@0: $output = $on; Chris@0: } Chris@0: else { Chris@0: $output = '1'; Chris@0: } Chris@0: Chris@0: $elements = $this->xpath('//div[text()="' . $output . '"]'); Chris@0: $this->assertEqual(count($elements), 1, 'Correct options found.'); Chris@0: } Chris@0: } Chris@0: Chris@0: }