Skip to content

Commit b4310e4

Browse files
committed
Add CI workflow and tests
1 parent 42999bd commit b4310e4

File tree

7 files changed

+421
-1
lines changed

7 files changed

+421
-1
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
.gitignore text eol=lf
1717

1818
# Exclude from export (composer --prefer-dist)
19+
/.github export-ignore
1920
/tests export-ignore
2021
.editorconfig export-ignore
2122
.gitattributes export-ignore

.github/workflows/ci.yml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
8+
jobs:
9+
testsuite:
10+
runs-on: ubuntu-latest
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
php-version: ['8.1', '8.2', '8.3']
15+
laravel-version: ['10.*', '11.*']
16+
exclude:
17+
- php-version: '8.1'
18+
laravel-version: '11.*'
19+
20+
name: PHP ${{ matrix.php-version }} / Laravel ${{ matrix.laravel-version }}
21+
22+
steps:
23+
- uses: actions/checkout@v4
24+
25+
- name: Setup PHP
26+
uses: shivammathur/setup-php@v2
27+
with:
28+
php-version: ${{ matrix.php-version }}
29+
extensions: mbstring
30+
coverage: none
31+
32+
- name: Get composer cache directory
33+
id: composercache
34+
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
35+
36+
- name: Cache dependencies
37+
uses: actions/cache@v4
38+
with:
39+
path: ${{ steps.composercache.outputs.dir }}
40+
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
41+
restore-keys: ${{ runner.os }}-composer-
42+
43+
- name: Install dependencies
44+
run: |
45+
composer require "laravel/framework:${{ matrix.laravel-version }}" --no-interaction --no-update
46+
composer install --prefer-dist --no-progress
47+
48+
- name: Run tests
49+
run: vendor/bin/phpunit
50+
51+
validation:
52+
runs-on: ubuntu-latest
53+
name: Coding Standard & Static Analysis
54+
55+
steps:
56+
- uses: actions/checkout@v4
57+
58+
- name: Setup PHP
59+
uses: shivammathur/setup-php@v2
60+
with:
61+
php-version: '8.2'
62+
extensions: mbstring
63+
coverage: none
64+
65+
- name: Get composer cache directory
66+
id: composercache
67+
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
68+
69+
- name: Cache dependencies
70+
uses: actions/cache@v4
71+
with:
72+
path: ${{ steps.composercache.outputs.dir }}
73+
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
74+
restore-keys: ${{ runner.os }}-composer-
75+
76+
- name: Install dependencies
77+
run: composer install --prefer-dist --no-progress
78+
79+
- name: Run PHPStan
80+
run: composer stan
81+
82+
- name: Run PHPCS
83+
run: composer cs-check

composer.json

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,55 @@
33
"description": "Laravel integration for php-collective/dto",
44
"type": "library",
55
"license": "MIT",
6+
"keywords": [
7+
"dto",
8+
"laravel",
9+
"data-transfer-object"
10+
],
611
"require": {
712
"php": ">=8.1",
813
"php-collective/dto": "^0.1|dev-master",
914
"laravel/framework": "^10.0|^11.0|^12.0"
1015
},
16+
"require-dev": {
17+
"orchestra/testbench": "^8.0|^9.0|^10.0",
18+
"php-collective/code-sniffer": "dev-master",
19+
"phpstan/phpstan": "^2.1",
20+
"phpunit/phpunit": "^10.0|^11.0|^12.0"
21+
},
1122
"autoload": {
1223
"psr-4": {
1324
"PhpCollective\\LaravelDto\\": "src/"
1425
}
1526
},
27+
"autoload-dev": {
28+
"psr-4": {
29+
"PhpCollective\\LaravelDto\\Test\\": "tests/"
30+
}
31+
},
32+
"scripts": {
33+
"check": [
34+
"@cs-check",
35+
"@test"
36+
],
37+
"cs-check": "phpcs --colors --parallel=16",
38+
"cs-fix": "phpcbf --colors --parallel=16",
39+
"stan": "phpstan analyze",
40+
"test": "phpunit"
41+
},
1642
"extra": {
1743
"laravel": {
1844
"providers": [
1945
"PhpCollective\\LaravelDto\\DtoServiceProvider"
2046
]
2147
}
22-
}
48+
},
49+
"config": {
50+
"allow-plugins": {
51+
"dealerdirect/phpcodesniffer-composer-installer": true
52+
},
53+
"sort-packages": true
54+
},
55+
"minimum-stability": "stable",
56+
"prefer-stable": true
2357
}

phpstan.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ parameters:
22
level: 8
33
paths:
44
- src/
5+
- tests/
56
ignoreErrors:
67
- identifier: missingType.iterableValue
78
- identifier: missingType.generics

tests/DtoServiceProviderTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpCollective\LaravelDto\Test;
6+
7+
use Illuminate\Support\Collection;
8+
use Orchestra\Testbench\TestCase;
9+
use PhpCollective\Dto\Dto\Dto;
10+
use PhpCollective\LaravelDto\DtoServiceProvider;
11+
use PhpCollective\LaravelDto\GenerateDtoCommand;
12+
13+
class DtoServiceProviderTest extends TestCase
14+
{
15+
/**
16+
* @param \Illuminate\Foundation\Application $app
17+
*
18+
* @return array<int, class-string>
19+
*/
20+
protected function getPackageProviders($app): array
21+
{
22+
return [
23+
DtoServiceProvider::class,
24+
];
25+
}
26+
27+
public function testServiceProviderIsLoaded(): void
28+
{
29+
$this->assertTrue($this->app->providerIsLoaded(DtoServiceProvider::class));
30+
}
31+
32+
public function testConfigIsMerged(): void
33+
{
34+
$config = $this->app['config']->get('dto');
35+
36+
$this->assertIsArray($config);
37+
$this->assertArrayHasKey('config_path', $config);
38+
$this->assertArrayHasKey('output_path', $config);
39+
$this->assertArrayHasKey('namespace', $config);
40+
}
41+
42+
public function testCommandIsRegistered(): void
43+
{
44+
$this->assertTrue($this->app->bound(GenerateDtoCommand::class));
45+
}
46+
47+
public function testCollectionFactoryIsConfigured(): void
48+
{
49+
// After boot, the collection factory should be set to Laravel's collect()
50+
$items = ['a', 'b', 'c'];
51+
$collection = Dto::getCollectionFactory()($items);
52+
53+
$this->assertInstanceOf(Collection::class, $collection);
54+
$this->assertSame($items, $collection->toArray());
55+
}
56+
}

tests/GenerateDtoCommandTest.php

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpCollective\LaravelDto\Test;
6+
7+
use Orchestra\Testbench\TestCase;
8+
use PhpCollective\LaravelDto\DtoServiceProvider;
9+
10+
class GenerateDtoCommandTest extends TestCase
11+
{
12+
protected string $tempDir;
13+
14+
/**
15+
* @param \Illuminate\Foundation\Application $app
16+
*
17+
* @return array<int, class-string>
18+
*/
19+
protected function getPackageProviders($app): array
20+
{
21+
return [
22+
DtoServiceProvider::class,
23+
];
24+
}
25+
26+
protected function setUp(): void
27+
{
28+
parent::setUp();
29+
30+
$this->tempDir = sys_get_temp_dir() . '/laravel_dto_test_' . uniqid();
31+
mkdir($this->tempDir, 0777, true);
32+
mkdir($this->tempDir . '/config', 0777, true);
33+
mkdir($this->tempDir . '/output', 0777, true);
34+
}
35+
36+
protected function tearDown(): void
37+
{
38+
$this->removeDirectory($this->tempDir);
39+
parent::tearDown();
40+
}
41+
42+
protected function removeDirectory(string $dir): void
43+
{
44+
if (!is_dir($dir)) {
45+
return;
46+
}
47+
$files = array_diff(scandir($dir), ['.', '..']);
48+
foreach ($files as $file) {
49+
$path = $dir . '/' . $file;
50+
is_dir($path) ? $this->removeDirectory($path) : unlink($path);
51+
}
52+
rmdir($dir);
53+
}
54+
55+
/**
56+
* @param \Illuminate\Foundation\Application $app
57+
*/
58+
protected function defineEnvironment($app): void
59+
{
60+
$app['config']->set('dto.config_path', $this->tempDir . '/config');
61+
$app['config']->set('dto.output_path', $this->tempDir . '/output');
62+
$app['config']->set('dto.namespace', 'TestApp\\Dto');
63+
}
64+
65+
public function testCommandExists(): void
66+
{
67+
$this->assertTrue($this->app['artisan']->has('dto:generate'));
68+
}
69+
70+
public function testCommandWithDryRun(): void
71+
{
72+
$configContent = <<<'XML'
73+
<?xml version="1.0" encoding="UTF-8"?>
74+
<dtos xmlns="php-collective-dto">
75+
<dto name="User">
76+
<field name="id" type="int"/>
77+
<field name="name" type="string"/>
78+
</dto>
79+
</dtos>
80+
XML;
81+
file_put_contents($this->tempDir . '/config/dto.xml', $configContent);
82+
83+
$this->artisan('dto:generate', ['--dry-run' => true])
84+
->assertSuccessful();
85+
86+
// With dry-run, no files should be created
87+
$this->assertFileDoesNotExist($this->tempDir . '/output/Dto/UserDto.php');
88+
}
89+
90+
public function testCommandGeneratesDto(): void
91+
{
92+
$configContent = <<<'XML'
93+
<?xml version="1.0" encoding="UTF-8"?>
94+
<dtos xmlns="php-collective-dto">
95+
<dto name="User">
96+
<field name="id" type="int"/>
97+
<field name="name" type="string"/>
98+
</dto>
99+
</dtos>
100+
XML;
101+
file_put_contents($this->tempDir . '/config/dto.xml', $configContent);
102+
103+
$this->artisan('dto:generate')
104+
->assertSuccessful();
105+
106+
$this->assertFileExists($this->tempDir . '/output/Dto/UserDto.php');
107+
108+
$content = file_get_contents($this->tempDir . '/output/Dto/UserDto.php');
109+
$this->assertStringContainsString('namespace TestApp\\Dto', $content);
110+
$this->assertStringContainsString('class UserDto', $content);
111+
}
112+
}

0 commit comments

Comments
 (0)