<?php namespace Codeception\Module; use Codeception\Util\FileSystem as Util; use Symfony\Component\Finder\Finder; use Codeception\Module as CodeceptionModule; use Codeception\TestInterface; use Codeception\Configuration; /** * Module for testing local filesystem. * Fork it to extend the module for FTP, Amazon S3, others. * * ## Status * * * Maintainer: **davert** * * Stability: **stable** * * Contact: codecept@davert.mail.ua * * Module was developed to test Codeception itself. */ class Filesystem extends CodeceptionModule { protected $file = null; protected $filepath = null; protected $path = ''; public function _before(TestInterface $test) { $this->path = Configuration::projectDir(); } /** * Enters a directory In local filesystem. * Project root directory is used by default * * @param string $path */ public function amInPath($path) { chdir($this->path = $this->absolutizePath($path) . DIRECTORY_SEPARATOR); $this->debug('Moved to ' . getcwd()); } /** * @param string $path * @return string */ protected function absolutizePath($path) { // *nix way if (strpos($path, '/') === 0) { return $path; } // windows if (strpos($path, ':\\') === 1) { return $path; } return $this->path . $path; } /** * Opens a file and stores it's content. * * Usage: * * ``` php * <?php * $I->openFile('composer.json'); * $I->seeInThisFile('codeception/codeception'); * ?> * ``` * * @param string $filename */ public function openFile($filename) { $this->file = file_get_contents($this->absolutizePath($filename)); $this->filepath = $filename; } /** * Deletes a file * * ``` php * <?php * $I->deleteFile('composer.lock'); * ?> * ``` * * @param string $filename */ public function deleteFile($filename) { if (!file_exists($this->absolutizePath($filename))) { \PHPUnit\Framework\Assert::fail('file not found'); } unlink($this->absolutizePath($filename)); } /** * Deletes directory with all subdirectories * * ``` php * <?php * $I->deleteDir('vendor'); * ?> * ``` * * @param string $dirname */ public function deleteDir($dirname) { $dir = $this->absolutizePath($dirname); Util::deleteDir($dir); } /** * Copies directory with all contents * * ``` php * <?php * $I->copyDir('vendor','old_vendor'); * ?> * ``` * * @param string $src * @param string $dst */ public function copyDir($src, $dst) { Util::copyDir($src, $dst); } /** * Checks If opened file has `text` in it. * * Usage: * * ``` php * <?php * $I->openFile('composer.json'); * $I->seeInThisFile('codeception/codeception'); * ?> * ``` * * @param string $text */ public function seeInThisFile($text) { $this->assertContains($text, $this->file, "No text '$text' in currently opened file"); } /** * Checks If opened file has the `number` of new lines. * * Usage: * * ``` php * <?php * $I->openFile('composer.json'); * $I->seeNumberNewLines(5); * ?> * ``` * * @param int $number New lines */ public function seeNumberNewLines($number) { $lines = preg_split('/\n|\r/', $this->file); $this->assertTrue( (int) $number === count($lines), "The number of new lines does not match with $number" ); } /** * Checks that contents of currently opened file matches $regex * * @param string $regex */ public function seeThisFileMatches($regex) { $this->assertRegExp($regex, $this->file, "Contents of currently opened file does not match '$regex'"); } /** * Checks the strict matching of file contents. * Unlike `seeInThisFile` will fail if file has something more than expected lines. * Better to use with HEREDOC strings. * Matching is done after removing "\r" chars from file content. * * ``` php * <?php * $I->openFile('process.pid'); * $I->seeFileContentsEqual('3192'); * ?> * ``` * * @param string $text */ public function seeFileContentsEqual($text) { $file = str_replace("\r", '', $this->file); \PHPUnit\Framework\Assert::assertEquals($text, $file); } /** * Checks If opened file doesn't contain `text` in it * * ``` php * <?php * $I->openFile('composer.json'); * $I->dontSeeInThisFile('codeception/codeception'); * ?> * ``` * * @param string $text */ public function dontSeeInThisFile($text) { $this->assertNotContains($text, $this->file, "Found text '$text' in currently opened file"); } /** * Deletes a file */ public function deleteThisFile() { $this->deleteFile($this->filepath); } /** * Checks if file exists in path. * Opens a file when it's exists * * ``` php * <?php * $I->seeFileFound('UserModel.php','app/models'); * ?> * ``` * * @param string $filename * @param string $path */ public function seeFileFound($filename, $path = '') { if ($path === '' && file_exists($filename)) { $this->openFile($filename); \PHPUnit\Framework\Assert::assertFileExists($filename); return; } $found = $this->findFileInPath($filename, $path); if ($found === false) { $this->fail("File \"$filename\" not found at \"$path\""); } $this->openFile($found); \PHPUnit\Framework\Assert::assertFileExists($found); } /** * Checks if file does not exist in path * * @param string $filename * @param string $path */ public function dontSeeFileFound($filename, $path = '') { if ($path === '') { \PHPUnit\Framework\Assert::assertFileNotExists($filename); return; } $found = $this->findFileInPath($filename, $path); if ($found === false) { //this line keeps a count of assertions correct \PHPUnit\Framework\Assert::assertTrue(true); return; } \PHPUnit\Framework\Assert::assertFileNotExists($found); } /** * Finds the first matching file * * @param string $filename * @param string $path * @throws \PHPUnit\Framework\AssertionFailedError When path does not exist * @return string|false Path to the first matching file */ private function findFileInPath($filename, $path) { $path = $this->absolutizePath($path); if (!file_exists($path)) { $this->fail("Directory does not exist: $path"); } $files = Finder::create()->files()->name($filename)->in($path); if ($files->count() === 0) { return false; } foreach ($files as $file) { return $file->getRealPath(); } } /** * Erases directory contents * * ``` php * <?php * $I->cleanDir('logs'); * ?> * ``` * * @param string $dirname */ public function cleanDir($dirname) { $path = $this->absolutizePath($dirname); Util::doEmptyDir($path); } /** * Saves contents to file * * @param string $filename * @param string $contents */ public function writeToFile($filename, $contents) { file_put_contents($filename, $contents); } }