/**
  * Create a node of the specified type.
  *
  * Note that this will not log the user in, so you need to make sure you are already logged in with a user with
  * sufficient privileges to access the desired node creation page.
  *
  * @param WebInterface $I
  *   A reference to the Actor object being used.
  * @param string $type
  *   The machine name of the content type to be created.
  * @param array $data
  *   If you want to provide custom data, the keys in this array should be the machine names of the fields to be
  *   filled, and the values should be the data to be used. Any fields ommitted here will use any testData from
  *   contentTypes.yml to obtain their values.
  * @param string|null $role
  *   The role being used to fill out the node edit form. This is used to determine which fields need to be skipped
  *   for the current role (as not all fields will appear for all roles). If not provided, no role will be assumed
  *   and all fields will be used.
  *
  * @return int
  *   The node ID of the node that has just been created.
  */
 public function createNode($I, $type, $data = array(), $role = null)
 {
     // Make sure we are trying to create a valid content type.
     if (!$this->isValidContentType($type)) {
         throw new InvalidArgumentException('"' . $type . '" is not a valid content type');
     }
     $I->amOnPage(AdminNodeAddPage::route($type));
     $contentType = $this->getContentType($type);
     $title = '';
     foreach ($contentType->getFields() as $field) {
         // Skip this field if we are using a role that doesn't see it.
         if ($field->isSkipped($role)) {
             continue;
         }
         // Save the title to check later on that the node was created properly.
         if ($field->getMachine() == 'title') {
             // If we've passed in a custom title use that, otherwise use the default field test data.
             if (isset($data['title'])) {
                 $title = $data['title'];
             } else {
                 $title = $field->getTestData();
             }
         }
         if (isset($data[$field->getMachine()])) {
             $field->fill($I, $data[$field->getMachine()]);
         } else {
             $field->fill($I);
         }
     }
     // Handle any 'extras' on the node creation form that aren't fields but still need user interaction.
     foreach ($contentType->getExtras() as $extra) {
         // Skip this extra if we are using a role that doesn't see it.
         if ($extra->isSkipped($role)) {
             continue;
         }
         if (isset($data[$extra->getMachine()])) {
             $extra->fill($I, $data[$extra->getMachine()]);
         } else {
             $extra->fill($I);
         }
     }
     // Submit the node.
     $I->click($contentType->getSubmitSelector());
     // Check that the node was created properly.
     $msg = sprintf('%s %s has been created.', $contentType->getHumanName(), $title);
     $nid = $I->grabLastCreatedNid($I);
     $I->seeCreateNodeWasSuccessful($I, $msg, $nid);
     return $nid;
 }
 /**
  * Create a node of the specified type.
  *
  * Note that this will not log the user in, so you need to make sure you are already logged in with a user with
  * sufficient privileges to access the desired node creation page.
  *
  * @param WebInterface $I
  *   A reference to the Actor object being used.
  * @param string $type
  *   The machine name of the content type to be created.
  * @param array $data
  *   If you want to provide custom data, the keys in this array should be the machine names of the fields to be
  *   filled, and the values should be the data to be used. Any fields omitted here will use any testData from
  *   contentTypes.yml to obtain their values.
  * @param string|null $role
  *   The role being used to fill out the node edit form. This is used to determine which fields need to be skipped
  *   for the current role (as not all fields will appear for all roles). If not provided, no role will be assumed
  *   and all fields will be used.
  *
  * @return int
  *   The node ID of the node that has just been created.
  */
 public function createNode($I, $type, $data = array(), $role = null)
 {
     // Make sure we are trying to create a valid content type.
     if (!$this->isValidContentType($type)) {
         throw new InvalidArgumentException('"' . $type . '" is not a valid content type');
     }
     $I->amOnPage(AdminNodeAddPage::route($type));
     $contentType = $this->getContentType($type);
     $title = '';
     $fields = array_merge($contentType->getFields(), $contentType->getExtras());
     /**
      * @var Field[] $fields
      */
     foreach ($fields as $field) {
         // Skip this field if we are using a role that doesn't see it.
         if ($field->isSkipped($role)) {
             continue;
         }
         // Save the title to check later on that the node was created properly.
         if ($field->getMachine() == 'title') {
             // If we've passed in a custom title use that, otherwise use the default field test data.
             if (isset($data['title'])) {
                 $title = $data['title'];
             } else {
                 $title = $field->getTestData();
             }
         }
         if (isset($data[$field->getMachine()])) {
             $field->fill($I, $data[$field->getMachine()]);
         } else {
             $field->fill($I);
         }
     }
     // On mobile resolutions, clicking the submit button does not do anything
     // unless it is in view first.
     $I->executeJS("document.querySelector('" . $contentType->getSubmitSelector() . "').scrollIntoView(true)");
     // Submit the node.
     $I->click($contentType->getSubmitSelector());
     // Check that the node was created properly.
     $msg = sprintf('%s %s has been created.', $contentType->getHumanName(), $title);
     $nid = $I->grabLastCreatedNid($I);
     $I->seeCreateNodeWasSuccessful($I, $msg, $nid);
     return $nid;
 }