diff --git a/psalm.xml b/psalm.xml
index 72d8e61a..ed3283e1 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -30,6 +30,14 @@
+
+
+
+
+
+
+
diff --git a/tests/Bridge/MoodleTest.php b/tests/Bridge/MoodleTest.php
index cb0a5e57..c1eed1d7 100644
--- a/tests/Bridge/MoodleTest.php
+++ b/tests/Bridge/MoodleTest.php
@@ -13,12 +13,116 @@
namespace MoodlePluginCI\Tests\Bridge;
use MoodlePluginCI\Bridge\Moodle;
+use MoodlePluginCI\Tests\FilesystemTestCase;
-class MoodleTest extends \PHPUnit\Framework\TestCase
+/**
+ * Test the \MoodlePluginCI\Bridge\Moodle class.
+ *
+ * Note that various unit tests are run in a separate process to avoid
+ * conflicts with global state when including Moodle's config.php or
+ * core_component (mocked) class.
+ *
+ * @covers \MoodlePluginCI\Bridge\Moodle
+ */
+class MoodleTest extends FilesystemTestCase
{
- public function testGetBranch(): void
+ /**
+ * @runInSeparateProcess
+ */
+ public function testGetConfigExists(): void
+ {
+ $this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);
+ $this->fs->copy(__DIR__ . '/../Fixture/tiny-config.php', $this->tempDir . '/config.php');
+ $moodle = new Moodle($this->tempDir);
+
+ $this->assertSame('exists', $moodle->getConfig('exists'));
+ }
+
+ /**
+ * @runInSeparateProcess
+ */
+ public function testGetConfigNotExists(): void
+ {
+ $this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);
+ $this->fs->copy(__DIR__ . '/../Fixture/tiny-config.php', $this->tempDir . '/config.php');
+ $moodle = new Moodle($this->tempDir);
+
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionMessage('Failed to find $CFG->notexists in Moodle config file');
+ $moodle->getConfig('notexists');
+ }
+
+ /**
+ * @runInSeparateProcess
+ */
+ public function testGetConfigNoConfigFile(): void
+ {
+ $this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);
+ $moodle = new Moodle($this->tempDir);
+
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionMessage('Failed to find Moodle config file');
+ $moodle->getConfig('wwwroot');
+ }
+
+ /**
+ * @runInSeparateProcess
+ */
+ public function testComponentInstallDirectoryExists(): void
{
- $moodle = new Moodle(__DIR__ . '/../Fixture/moodle');
+ $this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);
+ $this->fs->copy(__DIR__ . '/../Fixture/tiny-config.php', $this->tempDir . '/config.php');
+ $moodle = new Moodle($this->tempDir);
+
+ // Initially we tried to mock the core_component class with Mockery, and everything
+ // worked fine, but the use of Reflection that we have in the code to be tested.
+ // Hence, we have changed to load a minimal core_component (Fixture/moodle/lib/classes/component.php)
+ // class that will be used instead of the (core) original.
+ require_once $this->tempDir . '/lib/classes/component.php';
+
+ $this->assertSame('/path/to/mod/test', $moodle->getComponentInstallDirectory('mod_test'));
+ }
+
+ /**
+ * @runInSeparateProcess
+ */
+ public function testComponentInstallDirectoryNotExists(): void
+ {
+ $this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);
+ $this->fs->copy(__DIR__ . '/../Fixture/tiny-config.php', $this->tempDir . '/config.php');
+ $moodle = new Moodle($this->tempDir);
+
+ // Initially we tried to mock the core_component class with Mockery, and everything
+ // worked fine, but the use of Reflection that we have in the code to be tested.
+ // Hence, we have changed to load a minimal core_component (Fixture/moodle/lib/classes/component.php)
+ // class that will be used instead of the (core) original.
+ require_once $this->tempDir . '/lib/classes/component.php';
+
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('The component unknown_test has an unknown plugin type of unknown');
+ $moodle->getComponentInstallDirectory('unknown_test');
+ }
+
+ public function testGetBranchCorrect(): void
+ {
+ $this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);
+ $moodle = new Moodle($this->tempDir);
+
$this->assertSame(39, $moodle->getBranch());
}
+
+ public function testGetBranchIncorrect(): void
+ {
+ $this->fs->mirror(__DIR__ . '/../Fixture/moodle', $this->tempDir);
+
+ // Let's edit the version.php file to convert the correct (string) branch into incorrect (integer) branch.
+ $contents = file_get_contents($this->tempDir . '/version.php');
+ $contents = preg_replace("/'39'/", '39', $contents);
+ file_put_contents($this->tempDir . '/version.php', $contents);
+
+ $moodle = new Moodle($this->tempDir);
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionMessage('Failed to find Moodle branch version');
+ $moodle->getBranch();
+ }
}
diff --git a/tests/Command/MessDetectorCommandTest.php b/tests/Command/MessDetectorCommandTest.php
index 60d02dbb..d116f52c 100644
--- a/tests/Command/MessDetectorCommandTest.php
+++ b/tests/Command/MessDetectorCommandTest.php
@@ -52,6 +52,16 @@ public function testExecute(): void
$this->assertSame(0, $commandTester->getStatusCode());
}
+ public function testExecuteWithProblems(): void
+ {
+ $commandTester = $this->executeCommand(__DIR__ . '/../Fixture/phpmd');
+
+ $this->assertSame(0, $commandTester->getStatusCode()); // PHPMD always return 0, no matter the violations/errors.
+ $this->assertStringContainsString('Constant testConst should be defined in uppercase', $commandTester->getDisplay());
+ $this->assertStringContainsString('long variable names like $reallyVeryLongVariableName', $commandTester->getDisplay());
+ $this->assertStringContainsString('Unexpected end of token stream in file', $commandTester->getDisplay());
+ }
+
public function testExecuteNoFiles(): void
{
// Just random directory with no PHP files.
diff --git a/tests/Fixture/moodle/lib/classes/component.php b/tests/Fixture/moodle/lib/classes/component.php
new file mode 100644
index 00000000..ccd5279a
--- /dev/null
+++ b/tests/Fixture/moodle/lib/classes/component.php
@@ -0,0 +1,41 @@
+ '/path/to/mod', 'local' => '/path/to/local'],
+ [], // We don't need this.
+ [], // We don't need this.
+ ];
+ }
+}
diff --git a/tests/Fixture/phpmd/Problems.php b/tests/Fixture/phpmd/Problems.php
new file mode 100644
index 00000000..a396113e
--- /dev/null
+++ b/tests/Fixture/phpmd/Problems.php
@@ -0,0 +1,23 @@
+dbtype = 'mysqli';
+$CFG->dblibrary = 'native';
+$CFG->dbhost = 'localhost';
+$CFG->dbname = 'moodle';
+$CFG->dbuser = 'root';
+$CFG->dbpass = '';
+$CFG->prefix = 'mdl_';
+$CFG->dboptions = [
+ 'dbport' => '',
+];
+
+$CFG->wwwroot = 'http://localhost/moodle';
+$CFG->dataroot = '/path/to/moodledata';
+$CFG->admin = 'admin';
+
+$CFG->directorypermissions = 02777;
+
+// Show debugging messages.
+$CFG->debug = (E_ALL | E_STRICT);
+$CFG->debugdisplay = 1;
+
+// Extra config.
+$CFG->exists = 'exists';
+
+// require_once(__DIR__.'/lib/setup.php');
+// There is no php closing tag in this file,
+// it is intentional because it prevents trailing whitespace problems!