/**
  * Tests the country field.
  *
  * Checked:
  * - required/optional status.
  * - default_country widget setting.
  * - available_countries instance setting.
  */
 function testCountries()
 {
     $field_name = $this->field->getName();
     $edit = [];
     // Optional field: Country should be optional and set to default_country.
     $this->drupalGet($this->nodeAddUrl);
     $this->assertFalse((bool) $this->xpath('//select[@name="' . $field_name . '[0][country_code]" and boolean(@required)]'), 'Country is shown as optional.');
     $this->assertOptionSelected('edit-field-address-0-country-code', 'US', 'The configured default_country is selected.');
     // Required field: Country should be required and set to default_country.
     $this->field->setRequired(TRUE);
     $this->field->save();
     $this->drupalGet($this->nodeAddUrl);
     $this->assertTrue((bool) $this->xpath('//select[@name="' . $field_name . '[0][country_code]" and boolean(@required)]'), 'Country is shown as required.');
     $this->assertOptionSelected('edit-field-address-0-country-code', 'US', 'The configured default_country is selected.');
     // All countries should be present in the form.
     $countries = array_keys($this->countryRepository->getList());
     $this->assertOptions($field_name . '[0][country_code]', $countries, 'All countries are present.');
     // Limit the list of available countries.
     $countries = ['US', 'FR', 'BR', 'JP'];
     $edit['settings[available_countries][]'] = array_map(function ($country) {
         return $country;
     }, $countries);
     $this->drupalPostForm($this->fieldConfigUrl, $edit, t('Save settings'));
     $this->assertResponse(200);
     $this->drupalGet($this->nodeAddUrl);
     $this->assertOptions($field_name . '[0][country_code]', $countries, 'The restricted list of available countries is present.');
     // Create an article with one of them.
     $address = ['country_code' => 'US', 'recipient' => 'Some Recipient', 'organization' => 'Some Organization', 'address_line1' => '1098 Alta Ave', 'locality' => 'Mountain View', 'administrative_area' => 'US-CA', 'postal_code' => '94043'];
     $edit = [];
     $edit['title[0][value]'] = $this->randomMachineName(8);
     foreach ($address as $property => $value) {
         $path = $field_name . '[0][' . $property . ']';
         $edit[$path] = $value;
     }
     $this->drupalPostForm(NULL, $edit, t('Save'));
     $this->assertResponse(200);
     // Check that the article has been created.
     $node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
     $this->assertTrue($node, 'Created article ' . $edit['title[0][value]']);
     // Now remove 'US' from the list of available countries.
     $countries = ['FR', 'BR', 'JP'];
     $edit = [];
     $edit['settings[available_countries][]'] = array_map(function ($country) {
         return $country;
     }, $countries);
     $this->drupalPostForm($this->fieldConfigUrl, $edit, t('Save settings'));
     // Access the article's edit form and confirm the values are unchanged.
     // 'US' should be in the list along with the available countries and should
     // be selected.
     $this->drupalGet('node/' . $node->id() . '/edit');
     $this->assertFieldByName($field_name . '[0][recipient]', $address['recipient']);
     $this->assertFieldByName($field_name . '[0][organization]', $address['organization']);
     $this->assertFieldByName($field_name . '[0][address_line1]', $address['address_line1']);
     $this->assertFieldByName($field_name . '[0][locality]', $address['locality']);
     $this->assertOptionSelected('edit-field-address-0-administrative-area', $address['administrative_area']);
     $this->assertFieldByName($field_name . '[0][postal_code]', $address['postal_code']);
     $this->assertOptionSelected('edit-field-address-0-country-code', $address['country_code']);
     // Test the widget with only one available country.
     // Since the field is required, the country selector should be hidden.
     $countries = ['US'];
     $edit = [];
     $edit['settings[available_countries][]'] = array_map(function ($country) {
         return $country;
     }, $countries);
     $this->drupalPostForm($this->fieldConfigUrl, $edit, t('Save settings'));
     $this->drupalGet('node/' . $node->id() . '/edit');
     $this->assertNoFieldByName($field_name . '[0][country_code]');
     // Submitting the form should result in no data loss.
     $this->drupalPostForm(NULL, [], t('Save'));
     $this->drupalGet('node/' . $node->id() . '/edit');
     $this->assertFieldByName($field_name . '[0][recipient]', $address['recipient']);
     $this->assertFieldByName($field_name . '[0][organization]', $address['organization']);
     $this->assertFieldByName($field_name . '[0][address_line1]', $address['address_line1']);
     $this->assertFieldByName($field_name . '[0][locality]', $address['locality']);
     $this->assertOptionSelected('edit-field-address-0-administrative-area', $address['administrative_area']);
     $this->assertFieldByName($field_name . '[0][postal_code]', $address['postal_code']);
 }