Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ name: CI

on:
push:
branches:
- master
pull_request:
branches:
- master

jobs:
test:
Expand All @@ -16,7 +20,7 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
coverage: none
coverage: xdebug
- name: Cache Composer dependencies
uses: actions/cache@v3
with:
Expand All @@ -29,4 +33,9 @@ jobs:
- name: Run PHP CS Fixer
run: vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --dry-run --diff --allow-risky=yes
- name: Run PHPUnit
run: vendor/bin/phpunit
run: vendor/bin/phpunit --coverage-clover=coverage.xml
- name: Upload coverage
uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.php-version }}
path: coverage.xml
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ composer.phar
/.phpunit.result.cache
composer.lock
.idea
coverage.xml
5 changes: 5 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php">
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
<testsuites>
<testsuite name="unit">
<directory>tests</directory>
Expand Down
175 changes: 175 additions & 0 deletions tests/SymlinksFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,179 @@ public function testProcessThrowsExceptionForAbsoluteLink(): void
$this->expectExceptionMessage('Invalid symlink link path');
$factory->process();
}

public function testProcessThrowsExceptionWhenSymlinksIsNotArray(): void
{
$composer = new Composer();
$dispatcher = new EventDispatcher($composer, new NullIO());
$composer->setEventDispatcher($dispatcher);
$package = new RootPackage('test/test', '1.0.0', '1.0.0');
$package->setExtra([
'somework/composer-symlinks' => [
'symlinks' => 'invalid'
]
]);
$composer->setPackage($package);

$event = new Event('post-install-cmd', $composer, new NullIO());
$factory = new SymlinksFactory($event, new Filesystem());

$this->expectException(\SomeWork\Symlinks\InvalidArgumentException::class);
$this->expectExceptionMessage('The extra.somework/composer-symlinks.symlinks setting must be an array.');
$factory->process();
}

public function testProcessReturnsEmptyWhenNoSymlinksConfigured(): void
{
$composer = new Composer();
$dispatcher = new EventDispatcher($composer, new NullIO());
$composer->setEventDispatcher($dispatcher);
$package = new RootPackage('test/test', '1.0.0', '1.0.0');
$package->setExtra([]);
$composer->setPackage($package);

$event = new Event('post-install-cmd', $composer, new NullIO());
$factory = new SymlinksFactory($event, new Filesystem());
$symlinks = $factory->process();

$this->assertSame([], $symlinks);
}

public function testProcessSkipsMissingTargetGlobally(): void
{
$tmp = sys_get_temp_dir() . '/factory_' . uniqid();
mkdir($tmp);
$cwd = getcwd();
chdir($tmp);

$composer = new Composer();
$dispatcher = new EventDispatcher($composer, new NullIO());
$composer->setEventDispatcher($dispatcher);
$package = new RootPackage('test/test', '1.0.0', '1.0.0');
$package->setExtra([
'somework/composer-symlinks' => [
'symlinks' => [
'missing/file.txt' => 'link.txt'
],
'skip-missing-target' => true
]
]);
$composer->setPackage($package);

$event = new Event('post-install-cmd', $composer, new NullIO());
$factory = new SymlinksFactory($event, new Filesystem());
$symlinks = $factory->process();

$this->assertCount(0, $symlinks);

chdir($cwd);
}

public function testProcessSetsForceCreateFromConfig(): void
{
$tmp = sys_get_temp_dir() . '/factory_' . uniqid();
mkdir($tmp);
mkdir($tmp . '/target');
file_put_contents($tmp . '/target/file.txt', 'content');
$cwd = getcwd();
chdir($tmp);

$composer = new Composer();
$dispatcher = new EventDispatcher($composer, new NullIO());
$composer->setEventDispatcher($dispatcher);
$package = new RootPackage('test/test', '1.0.0', '1.0.0');
$package->setExtra([
'somework/composer-symlinks' => [
'symlinks' => [
'target/file.txt' => 'link.txt'
],
'force-create' => true
]
]);
$composer->setPackage($package);

$event = new Event('post-install-cmd', $composer, new NullIO());
$factory = new SymlinksFactory($event, new Filesystem());
$symlinks = $factory->process();

$this->assertCount(1, $symlinks);
$this->assertTrue($symlinks[0]->isForceCreate());

chdir($cwd);
}

public function testProcessThrowsExceptionForMissingTarget(): void
{
$tmp = sys_get_temp_dir() . '/factory_' . uniqid();
mkdir($tmp);
$cwd = getcwd();
chdir($tmp);

$composer = new Composer();
$dispatcher = new EventDispatcher($composer, new NullIO());
$composer->setEventDispatcher($dispatcher);
$package = new RootPackage('test/test', '1.0.0', '1.0.0');
$package->setExtra([
'somework/composer-symlinks' => [
'symlinks' => [
'missing/file.txt' => 'link.txt'
]
]
]);
$composer->setPackage($package);

$event = new Event('post-install-cmd', $composer, new NullIO());
$factory = new SymlinksFactory($event, new Filesystem());

$this->expectException(\SomeWork\Symlinks\InvalidArgumentException::class);
$this->expectExceptionMessage('The target path does not exists');

try {
$factory->process();
} finally {
chdir($cwd);
}
}

public function testProcessThrowsLinkDirectoryErrorOnEnsureDirectoryFailure(): void
{
$tmp = sys_get_temp_dir() . '/factory_' . uniqid();
mkdir($tmp);
mkdir($tmp . '/target');
file_put_contents($tmp . '/target/file.txt', 'content');
$cwd = getcwd();
chdir($tmp);

$composer = new Composer();
$dispatcher = new EventDispatcher($composer, new NullIO());
$composer->setEventDispatcher($dispatcher);
$package = new RootPackage('test/test', '1.0.0', '1.0.0');
$package->setExtra([
'somework/composer-symlinks' => [
'symlinks' => [
'target/file.txt' => 'dir/link.txt'
]
]
]);
$composer->setPackage($package);

$event = new Event('post-install-cmd', $composer, new NullIO());

$filesystem = $this->createMock(Filesystem::class);
$filesystem->method('isAbsolutePath')->willReturn(false);
$filesystem->expects($this->once())
->method('ensureDirectoryExists')
->willThrowException(new \RuntimeException('fail'));
$filesystem->expects($this->never())->method('relativeSymlink');

$factory = new SymlinksFactory($event, $filesystem);

$this->expectException(\SomeWork\Symlinks\LinkDirectoryError::class);

try {
$factory->process();
} finally {
chdir($cwd);
}
}
}
43 changes: 43 additions & 0 deletions tests/SymlinksProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,47 @@ public function testThrowsErrorWhenLinkExists(): void
$processor = new SymlinksProcessor(new Filesystem());
$processor->processSymlink($symlink);
}

public function testDryRunThrowsErrorWhenLinkExists(): void
{
$this->expectException(\SomeWork\Symlinks\LinkDirectoryError::class);

$tmp = sys_get_temp_dir() . '/processor_' . uniqid();
mkdir($tmp);
$target = $tmp . '/target.txt';
file_put_contents($target, 'data');

$link = $tmp . '/link.txt';
file_put_contents($link, 'old');

$symlink = (new Symlink())
->setTarget($target)
->setLink($link)
->setAbsolutePath(true);

$processor = new SymlinksProcessor(new Filesystem(), true);
$processor->processSymlink($symlink);
}

public function testProcessSymlinkCreatesRelativeLink(): void
{
$tmp = sys_get_temp_dir() . '/processor_' . uniqid();
mkdir($tmp);
mkdir($tmp . '/dir', 0777, true);
$target = $tmp . '/target.txt';
file_put_contents($target, 'data');

$link = $tmp . '/dir/link.txt';

$symlink = (new Symlink())
->setTarget($target)
->setLink($link);

$processor = new SymlinksProcessor(new Filesystem());
$result = $processor->processSymlink($symlink);

$this->assertTrue($result);
$this->assertTrue(is_link($link));
$this->assertSame(realpath($target), realpath(dirname($link) . '/' . readlink($link)));
}
}