Skip to content

Commit 93c8a54

Browse files
committed
feat(tests): add comprehensive tests for GitAttributes and License components
Signed-off-by: Felipe Sayão Lobato Abreu <github@mentordosnerds.com>
1 parent c5cd662 commit 93c8a54

8 files changed

Lines changed: 837 additions & 34 deletions

File tree

src/GitAttributes/CandidateProvider.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ public function files(): array
9494
'/codecov.yml',
9595
'/composer-normalize.json',
9696
'/composer-require-checker.json',
97+
'/context7.json',
9798
'/docker-compose.override.yml',
9899
'/docker-compose.yaml',
99100
'/docker-compose.yml',

src/License/Generator.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,17 @@
3838
/**
3939
* Creates a new Generator instance.
4040
*
41-
* @param Reader $reader The reader for extracting metadata from composer.json
42-
* @param Resolver $resolver The resolver for mapping license identifiers to templates
43-
* @param TemplateLoader $templateLoader The loader for reading template files
44-
* @param PlaceholderResolver $placeholderResolver The resolver for template placeholders
41+
* @param ReaderInterface $reader The reader for extracting metadata from composer.json
42+
* @param ResolverInterface $resolver The resolver for mapping license identifiers to templates
43+
* @param TemplateLoaderInterface $templateLoader The loader for reading template files
44+
* @param PlaceholderResolverInterface $placeholderResolver The resolver for template placeholders
4545
* @param Filesystem $filesystem The filesystem component for file operations
4646
*/
4747
public function __construct(
48-
private Reader $reader,
49-
private Resolver $resolver,
50-
private TemplateLoader $templateLoader,
51-
private PlaceholderResolver $placeholderResolver,
48+
private ReaderInterface $reader,
49+
private ResolverInterface $resolver,
50+
private TemplateLoaderInterface $templateLoader,
51+
private PlaceholderResolverInterface $placeholderResolver,
5252
private Filesystem $filesystem = new Filesystem()
5353
) {}
5454

src/PhpUnit/Runner/Extension/DevToolsExtension.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ public function __construct(
8383
* parameters passed by PHPUnit
8484
*
8585
* @return void
86+
*
87+
* @codeCoverageIgnore
8688
*/
8789
public function bootstrap(Configuration $configuration, Facade $facade, ParameterCollection $parameters): void
8890
{
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of fast-forward/dev-tools.
7+
*
8+
* This source file is subject to the license bundled
9+
* with this source code in the file LICENSE.
10+
*
11+
* @copyright Copyright (c) 2026 Felipe Sayão Lobato Abreu <github@mentordosnerds.com>
12+
* @license https://opensource.org/licenses/MIT MIT License
13+
*
14+
* @see https://github.com/php-fast-forward/dev-tools
15+
* @see https://github.com/php-fast-forward
16+
* @see https://datatracker.ietf.org/doc/html/rfc2119
17+
*/
18+
19+
namespace FastForward\DevTools\Tests\GitAttributes;
20+
21+
use FastForward\DevTools\GitAttributes\CandidateProvider;
22+
use PHPUnit\Framework\Attributes\CoversClass;
23+
use PHPUnit\Framework\Attributes\Test;
24+
use PHPUnit\Framework\TestCase;
25+
26+
#[CoversClass(CandidateProvider::class)]
27+
final class CandidateProviderTest extends TestCase
28+
{
29+
private readonly CandidateProvider $provider;
30+
31+
/**
32+
* @return void
33+
*/
34+
protected function setUp(): void
35+
{
36+
$this->provider = new CandidateProvider();
37+
}
38+
39+
/**
40+
* @return void
41+
*/
42+
#[Test]
43+
public function foldersWillReturnNonEmptyArray(): void
44+
{
45+
self::assertNotEmpty($this->provider->folders());
46+
}
47+
48+
/**
49+
* @return void
50+
*/
51+
#[Test]
52+
public function foldersWillStartWithSlash(): void
53+
{
54+
self::assertStringStartsWith('/', $this->provider->folders()[0]);
55+
}
56+
57+
/**
58+
* @return void
59+
*/
60+
#[Test]
61+
public function foldersWillEndWithSlash(): void
62+
{
63+
$folders = $this->provider->folders();
64+
65+
self::assertStringEndsWith('/', $folders[0]);
66+
}
67+
68+
/**
69+
* @return void
70+
*/
71+
#[Test]
72+
public function filesWillReturnNonEmptyArray(): void
73+
{
74+
self::assertNotEmpty($this->provider->files());
75+
}
76+
77+
/**
78+
* @return void
79+
*/
80+
#[Test]
81+
public function filesWillStartWithSlash(): void
82+
{
83+
self::assertStringStartsWith('/', $this->provider->files()[0]);
84+
}
85+
86+
/**
87+
* @return void
88+
*/
89+
#[Test]
90+
public function filesWillNotEndWithSlash(): void
91+
{
92+
$files = $this->provider->files();
93+
94+
self::assertStringEndsNotWith('/', $files[0]);
95+
}
96+
97+
/**
98+
* @return void
99+
*/
100+
#[Test]
101+
public function allWillCombineFoldersAndFiles(): void
102+
{
103+
self::assertCount(
104+
\count($this->provider->folders()) + \count($this->provider->files()),
105+
$this->provider->all(),
106+
);
107+
}
108+
109+
/**
110+
* @return void
111+
*/
112+
#[Test]
113+
public function allWillHaveFoldersFirst(): void
114+
{
115+
$all = $this->provider->all();
116+
$foldersCount = \count($this->provider->folders());
117+
118+
self::assertSame($this->provider->folders(), \array_slice($all, 0, $foldersCount));
119+
}
120+
121+
/**
122+
* @return void
123+
*/
124+
#[Test]
125+
public function allWillHaveFilesAfterFolders(): void
126+
{
127+
$all = $this->provider->all();
128+
129+
$foldersCount = \count($this->provider->folders());
130+
131+
self::assertSame($this->provider->files(), \array_slice($all, $foldersCount));
132+
}
133+
134+
/**
135+
* @return void
136+
*/
137+
#[Test]
138+
public function folderWillContainDotGithub(): void
139+
{
140+
self::assertContains('/.github/', $this->provider->folders());
141+
}
142+
143+
/**
144+
* @return void
145+
*/
146+
#[Test]
147+
public function filesWillContainGitignore(): void
148+
{
149+
self::assertContains('/.gitignore', $this->provider->files());
150+
}
151+
}
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of fast-forward/dev-tools.
7+
*
8+
* This source file is subject to the license bundled
9+
* with this source code in the file LICENSE.
10+
*
11+
* @copyright Copyright (c) 2026 Felipe Sayão Lobato Abreu <github@mentordosnerds.com>
12+
* @license https://opensource.org/licenses/MIT MIT License
13+
*
14+
* @see https://github.com/php-fast-forward/dev-tools
15+
* @see https://github.com/php-fast-forward
16+
* @see https://datatracker.ietf.org/doc/html/rfc2119
17+
*/
18+
19+
namespace FastForward\DevTools\Tests\GitAttributes;
20+
21+
use FastForward\DevTools\GitAttributes\ExistenceChecker;
22+
use PHPUnit\Framework\Attributes\CoversClass;
23+
use PHPUnit\Framework\Attributes\Test;
24+
use PHPUnit\Framework\TestCase;
25+
use Prophecy\PhpUnit\ProphecyTrait;
26+
use Prophecy\Prophecy\ObjectProphecy;
27+
use Symfony\Component\Filesystem\Filesystem;
28+
29+
#[CoversClass(ExistenceChecker::class)]
30+
final class ExistenceCheckerTest extends TestCase
31+
{
32+
use ProphecyTrait;
33+
34+
/**
35+
* @property ObjectProphecy<Filesystem> $filesystem
36+
*/
37+
private readonly ObjectProphecy $filesystem;
38+
39+
private readonly ExistenceChecker $checker;
40+
41+
/**
42+
* @return void
43+
*/
44+
protected function setUp(): void
45+
{
46+
$this->filesystem = $this->prophesize(Filesystem::class);
47+
$this->checker = new ExistenceChecker($this->filesystem->reveal());
48+
}
49+
50+
/**
51+
* @return void
52+
*/
53+
#[Test]
54+
public function existsWillReturnTrueWhenPathExists(): void
55+
{
56+
$this->filesystem->exists('/project/.github/')
57+
->willReturn(true)
58+
->shouldBeCalledOnce();
59+
60+
self::assertTrue($this->checker->exists('/project', '/.github/'));
61+
}
62+
63+
/**
64+
* @return void
65+
*/
66+
#[Test]
67+
public function existsWillReturnFalseWhenPathDoesNotExist(): void
68+
{
69+
$this->filesystem->exists('/project/.nonexistent/')
70+
->willReturn(false)
71+
->shouldBeCalledOnce();
72+
73+
self::assertFalse($this->checker->exists('/project', '/.nonexistent/'));
74+
}
75+
76+
/**
77+
* @return void
78+
*/
79+
#[Test]
80+
public function filterExistingWillKeepOnlyExistingPaths(): void
81+
{
82+
$this->filesystem->exists('/project/.github/')
83+
->willReturn(true);
84+
$this->filesystem->exists('/project/README.md')
85+
->willReturn(false);
86+
$this->filesystem->exists('/project/docs/')
87+
->willReturn(true);
88+
89+
$result = $this->checker->filterExisting('/project', ['/.github/', '/README.md', '/docs/']);
90+
91+
self::assertSame(['/.github/', '/docs/'], $result);
92+
}
93+
94+
/**
95+
* @return void
96+
*/
97+
#[Test]
98+
public function filterExistingWillReturnEmptyArrayWhenNoneExist(): void
99+
{
100+
$this->filesystem->exists('/project/fake1')
101+
->willReturn(false);
102+
$this->filesystem->exists('/project/fake2')
103+
->willReturn(false);
104+
105+
$result = $this->checker->filterExisting('/project', ['/fake1', '/fake2']);
106+
107+
self::assertSame([], $result);
108+
}
109+
110+
/**
111+
* @return void
112+
*/
113+
#[Test]
114+
public function isDirectoryWillReturnTrueForDirectory(): void
115+
{
116+
self::assertTrue($this->checker->isDirectory(__DIR__, ''));
117+
}
118+
119+
/**
120+
* @return void
121+
*/
122+
#[Test]
123+
public function isDirectoryWillReturnFalseForFile(): void
124+
{
125+
self::assertFalse($this->checker->isDirectory(__DIR__, '/ExistenceCheckerTest.php'));
126+
}
127+
128+
/**
129+
* @return void
130+
*/
131+
#[Test]
132+
public function isFileWillReturnTrueForFile(): void
133+
{
134+
self::assertTrue($this->checker->isFile(__DIR__, '/ExistenceCheckerTest.php'));
135+
}
136+
137+
/**
138+
* @return void
139+
*/
140+
#[Test]
141+
public function isFileWillReturnFalseForDirectory(): void
142+
{
143+
self::assertFalse($this->checker->isFile(__DIR__, ''));
144+
}
145+
146+
/**
147+
* @return void
148+
*/
149+
#[Test]
150+
public function isDirectoryWillReturnFalseForNonExistent(): void
151+
{
152+
self::assertFalse($this->checker->isDirectory('/project', '/nonexistent'));
153+
}
154+
155+
/**
156+
* @return void
157+
*/
158+
#[Test]
159+
public function isFileWillReturnFalseForNonExistent(): void
160+
{
161+
self::assertFalse($this->checker->isFile('/project', '/nonexistent.php'));
162+
}
163+
}

0 commit comments

Comments
 (0)