diff --git a/README.md b/README.md index ec78228..4f48bf6 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ The Palantir Behat Drupal Extension provides additional step definitions for tes * `NodeContext`: test viewing and editing nodes by title * `DrupalCommentContext`: test commenting functionality +* `DrupalFileContext`: add files in your tests * `DrupalOrganicGroupsContext`: test access to Organic Groups * `DrupalSetupContext`: test for enabled modules and overridden features * `EntityDataContext`: test field data and properties on nodes, terms, and users directly, without relying on output (or write a simpletest...) diff --git a/src/Palantirnet/PalantirBehatExtension/Context/DrupalFileContext.php b/src/Palantirnet/PalantirBehatExtension/Context/DrupalFileContext.php new file mode 100644 index 0000000..25a459b --- /dev/null +++ b/src/Palantirnet/PalantirBehatExtension/Context/DrupalFileContext.php @@ -0,0 +1,50 @@ + $filename, + 'status' => $status, + ); + + $file = $this->expandFile($file); + + $this->fileCreate($file); + } + + /** + * @Given files: + * + * Given files: + * | filename | status | author | + * | example.pdf | 1 | Somebody | + * | test.png | 0 | Admin | + * | ... | ... | ... | + */ + public function createFiles(TableNode $filesTable) + { + foreach ($filesTable->getHash() as $fileHash) { + $file = (object) $fileHash; + $file = $this->expandFile($file); + + $this->fileCreate($file); + } + } + +} diff --git a/src/Palantirnet/PalantirBehatExtension/Context/SharedDrupalContext.php b/src/Palantirnet/PalantirBehatExtension/Context/SharedDrupalContext.php index 770ee3b..5310876 100644 --- a/src/Palantirnet/PalantirBehatExtension/Context/SharedDrupalContext.php +++ b/src/Palantirnet/PalantirBehatExtension/Context/SharedDrupalContext.php @@ -3,6 +3,12 @@ * @file * Behat context class with functionality that is shared across custom contexts. * + * @todo this work is currently tied to Drupal 7, because it runs some Drupal + * code, rather than using the DrupalDriver cores. This needs to be fixed, + * but lots of the functionality we want is not available in the core + * classes. At the very least, we should be able to get the Drupal version + * with $this->getDriver()->getDrupalVersion(). + * * @copyright (c) Copyright 2015 Palantir.net, Inc. */ @@ -117,4 +123,95 @@ public function findUserByName($userName) } } + + /** + * Save a file. + * + * @param stdclass $file + * A simple object representing file data. Properties should be a simple + * scalar values. Files may use either the 'uid' or 'author' fields to + * attribute the file to a particular Drupal user. + * + * @return stdclass + * A Drupal file object. + */ + public function fileCreate($file) + { + // Save the file. + $dest = file_build_uri(drupal_basename($file->uri)); + $result = file_copy($file, $dest); + + // Stash the file object for later cleanup. + if (!empty($result->fid)) { + $this->files[] = $result; + } + else { + throw new \Exception(sprintf('File "%s" could not be copied from "%s" to "%s".', $file->filename, $file->uri, $result->uri)); + } + + return $result; + } + + /** + * Add required file properties. + * + * @param stdclass $file + * A simple object representing file data. The 'filename' property is + * required. + * + * @return stdclass + * A file object with at least the filename, uri, uid, and status + * properties. + */ + public function expandFile($file) + { + if (empty($file->filename)) { + throw new \Exception("Can't create file with no source filename; this should be the name of a file within the MinkExtension's files_path directory."); + } + + // Set the URI to the path to the file within the MinkExtension's + // files_path parameter. + $file->uri = rtrim(realpath($this->getMinkParameter('files_path')), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $file->filename; + + // Assign authorship if none exists and `author` is passed. + if (!isset($file->uid) && !empty($file->author) && ($account = user_load_by_name($file->author))) { + $file->uid = $account->uid; + } + + // Add default values. + $defaults = array( + 'uid' => 0, + 'status' => 1, + ); + + foreach ($defaults as $key => $default) { + if (!isset($file->$key)) { + $file->$key = $default; + } + } + + return $file; + } + + /** + * Keep track of files so they can be cleaned up. + * + * @var array + */ + protected $files = array(); + + /** + * Remove any created files. + * + * @AfterScenario + */ + public function cleanFiles() + { + foreach ($this->files as $file) { + file_delete($file, TRUE); + } + + $this->files = array(); + } + }