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
26 changes: 24 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Execute tests
run: composer test

type:
type_coverage:
runs-on: ubuntu-latest

name: Type Coverage
Expand All @@ -51,4 +51,26 @@ jobs:
run: composer update

- name: Execute tests
run: composer lint:type-coverage
run: composer test:type-coverage

coverage:
runs-on: ubuntu-latest

name: Coverage

steps:
- name: Checkout code
uses: actions/checkout@v5

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: curl, mbstring, zip, pcntl, pdo, pdo_sqlite, iconv
coverage: xdebug

- name: Install dependencies
run: composer update

- name: Execute tests
run: composer test:coverage
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,12 @@
],
"build": "@php vendor/bin/testbench workbench:build --ansi",
"clear": "@php vendor/bin/testbench package:purge-skeleton --ansi",
"lint:type-coverage": "@php vendor/bin/pest --type-coverage --compact --min=95",
"migrate": "@php vendor/bin/testbench migrate:fresh --seed --ansi",
"prepare": "@php vendor/bin/testbench package:discover --ansi",
"style": "vendor/bin/pint --parallel --ansi",
"test": "@php vendor/bin/pest --parallel --colors=always",
"test:coverage": "@php vendor/bin/pest --colors=always --coverage --compact --parallel --min=95",
"test:type-coverage": "@php vendor/bin/pest --type-coverage --compact --min=95",
"test:update": "@php vendor/bin/pest --colors=always --update-snapshots"
}
}
2 changes: 2 additions & 0 deletions src/Commands/FeedGenerateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ protected function feedable(FeedQuery $feeds): array
protected function messageYellow(string $message): string
{
if ($this->option('no-ansi')) {
// @codeCoverageIgnoreStart
return $message;
// @codeCoverageIgnoreEnd
}

return $this->yellow($message);
Expand Down
2 changes: 2 additions & 0 deletions src/Exceptions/OpenFeedException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

use RuntimeException;

// @codeCoverageIgnoreStart
class OpenFeedException extends RuntimeException
{
public function __construct(string $path)
{
parent::__construct("Unable to open file for writing: [$path]");
}
}
// @codeCoverageIgnoreEnd
2 changes: 2 additions & 0 deletions src/Exceptions/WriteFeedException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

use RuntimeException;

// @codeCoverageIgnoreStart
class WriteFeedException extends RuntimeException
{
public function __construct(string $path)
{
parent::__construct("Failed to write to the feed: [$path].");
}
}
// @codeCoverageIgnoreEnd
2 changes: 2 additions & 0 deletions src/Helpers/ClassExistsHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

use function class_exists;

// @codeCoverageIgnoreStart
class ClassExistsHelper
{
public function exists(string $class): bool
{
return class_exists($class);
}
}
// @codeCoverageIgnoreEnd
2 changes: 2 additions & 0 deletions src/LaravelFeedServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ public function register(): void

public function boot(): void
{
// @codeCoverageIgnoreStart
if (! $this->app->runningInConsole()) {
return;
}
// @codeCoverageIgnoreEnd

$this->registerCommands();
$this->publishConfig();
Expand Down
6 changes: 6 additions & 0 deletions src/Services/FilesystemService.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ public function open(string $path) // @pest-ignore-type
$resource = fopen($path, 'ab');

if ($resource === false) {
// @codeCoverageIgnoreStart
throw new OpenFeedException($path);
// @codeCoverageIgnoreEnd
}

return $resource;
Expand All @@ -50,7 +52,9 @@ public function append($resource, string $content, string $path): void // @pest-
}

if (fwrite($resource, $content) === false) {
// @codeCoverageIgnoreStart
throw new WriteFeedException($path);
// @codeCoverageIgnoreEnd
}
}

Expand All @@ -77,7 +81,9 @@ public function release($resource, string $path): void // @pest-ignore-type
public function close($resource): void // @pest-ignore-type
{
if (! is_resource($resource)) {
// @codeCoverageIgnoreStart
return;
// @codeCoverageIgnoreEnd
}

fclose($resource);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<FullFeed>
<news><record_title>[NEWS]:Some 1</record_title><record_content>Some content 1</record_content><extra>Some extra data</extra><with_attributes><Good_guy my-key-1="my value 1" my-key-2="my value 2"><name>Luke Skywalker</name><weapon>Lightsaber</weapon></Good_guy><Bad_guy><name><![CDATA[<h1>Sauron</h1>]]></name><weapon>Evil Eye</weapon></Bad_guy></with_attributes></news>
<news><record_title>[NEWS]:Some 2</record_title><record_content>Some content 2</record_content><extra>Some extra data</extra><with_attributes><Good_guy my-key-1="my value 1" my-key-2="my value 2"><name>Luke Skywalker</name><weapon>Lightsaber</weapon></Good_guy><Bad_guy><name><![CDATA[<h1>Sauron</h1>]]></name><weapon>Evil Eye</weapon></Bad_guy></with_attributes></news>
<news><record_title>[NEWS]:Some 3</record_title><record_content>Some content 3</record_content><extra>Some extra data</extra><with_attributes><Good_guy my-key-1="my value 1" my-key-2="my value 2"><name>Luke Skywalker</name><weapon>Lightsaber</weapon></Good_guy><Bad_guy><name><![CDATA[<h1>Sauron</h1>]]></name><weapon>Evil Eye</weapon></Bad_guy></with_attributes></news>
<news><record_title>[NEWS]:Some 1</record_title><record_content>Some content 1</record_content><extra>Some extra data</extra><with_attributes><Good_guy my-key-1="my value 1" my-key-2="my value 2"><name>Luke Skywalker</name><weapon>Lightsaber</weapon></Good_guy><Bad_guy><name><![CDATA[<h1>Sauron</h1>]]></name><weapon>Evil Eye</weapon></Bad_guy></with_attributes><with_mixed><first>line</first>
<second>line with <a href="https://example.com">some</a> html/xml tag</second>
<third>line with &amp; symbol</third></with_mixed></news>
<news><record_title>[NEWS]:Some 2</record_title><record_content>Some content 2</record_content><extra>Some extra data</extra><with_attributes><Good_guy my-key-1="my value 1" my-key-2="my value 2"><name>Luke Skywalker</name><weapon>Lightsaber</weapon></Good_guy><Bad_guy><name><![CDATA[<h1>Sauron</h1>]]></name><weapon>Evil Eye</weapon></Bad_guy></with_attributes><with_mixed><first>line</first>
<second>line with <a href="https://example.com">some</a> html/xml tag</second>
<third>line with &amp; symbol</third></with_mixed></news>
<news><record_title>[NEWS]:Some 3</record_title><record_content>Some content 3</record_content><extra>Some extra data</extra><with_attributes><Good_guy my-key-1="my value 1" my-key-2="my value 2"><name>Luke Skywalker</name><weapon>Lightsaber</weapon></Good_guy><Bad_guy><name><![CDATA[<h1>Sauron</h1>]]></name><weapon>Evil Eye</weapon></Bad_guy></with_attributes><with_mixed><first>line</first>
<second>line with <a href="https://example.com">some</a> html/xml tag</second>
<third>line with &amp; symbol</third></with_mixed></news>
</FullFeed>
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
<weapon>Evil Eye</weapon>
</Bad_guy>
</with_attributes>
<with_mixed><first>line</first>
<second>line with <a href="https://example.com">some</a> html/xml tag</second>
<third>line with &amp; symbol</third></with_mixed>
</news>
<news>
<record_title>[NEWS]:Some 2</record_title>
Expand All @@ -29,6 +32,9 @@
<weapon>Evil Eye</weapon>
</Bad_guy>
</with_attributes>
<with_mixed><first>line</first>
<second>line with <a href="https://example.com">some</a> html/xml tag</second>
<third>line with &amp; symbol</third></with_mixed>
</news>
<news>
<record_title>[NEWS]:Some 3</record_title>
Expand All @@ -44,5 +50,8 @@
<weapon>Evil Eye</weapon>
</Bad_guy>
</with_attributes>
<with_mixed><first>line</first>
<second>line with <a href="https://example.com">some</a> html/xml tag</second>
<third>line with &amp; symbol</third></with_mixed>
</news>
</FullFeed>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?><news><id>1</id><title>Some 1</title><content>Some content 1</content><created_at>2025-09-04T04:08:12.000000Z</created_at><updated_at>2025-09-04T04:08:12.000000Z</updated_at></news>
<news><id>2</id><title>Some 2</title><content>Some content 2</content><created_at>2025-09-04T04:08:12.000000Z</created_at><updated_at>2025-09-04T04:08:12.000000Z</updated_at></news>
<news><id>3</id><title>Some 3</title><content>Some content 3</content><created_at>2025-09-04T04:08:12.000000Z</created_at><updated_at>2025-09-04T04:08:12.000000Z</updated_at></news>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?><news>
<id>1</id>
<title>Some 1</title>
<content>Some content 1</content>
<created_at>2025-09-04T04:08:12.000000Z</created_at>
<updated_at>2025-09-04T04:08:12.000000Z</updated_at>
</news>
<news>
<id>2</id>
<title>Some 2</title>
<content>Some content 2</content>
<created_at>2025-09-04T04:08:12.000000Z</created_at>
<updated_at>2025-09-04T04:08:12.000000Z</updated_at>
</news>
<news>
<id>3</id>
<title>Some 3</title>
<content>Some content 3</content>
<created_at>2025-09-04T04:08:12.000000Z</created_at>
<updated_at>2025-09-04T04:08:12.000000Z</updated_at>
</news>
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<PartialFeed>
<news><record_title>[NEWS]:Some 1</record_title><record_content>Some content 1</record_content><extra>Some extra data</extra><with_attributes><Good_guy my-key-1="my value 1" my-key-2="my value 2"><name>Luke Skywalker</name><weapon>Lightsaber</weapon></Good_guy><Bad_guy><name><![CDATA[<h1>Sauron</h1>]]></name><weapon>Evil Eye</weapon></Bad_guy></with_attributes></news>
<news><record_title>[NEWS]:Some 2</record_title><record_content>Some content 2</record_content><extra>Some extra data</extra><with_attributes><Good_guy my-key-1="my value 1" my-key-2="my value 2"><name>Luke Skywalker</name><weapon>Lightsaber</weapon></Good_guy><Bad_guy><name><![CDATA[<h1>Sauron</h1>]]></name><weapon>Evil Eye</weapon></Bad_guy></with_attributes></news>
<news><record_title>[NEWS]:Some 3</record_title><record_content>Some content 3</record_content><extra>Some extra data</extra><with_attributes><Good_guy my-key-1="my value 1" my-key-2="my value 2"><name>Luke Skywalker</name><weapon>Lightsaber</weapon></Good_guy><Bad_guy><name><![CDATA[<h1>Sauron</h1>]]></name><weapon>Evil Eye</weapon></Bad_guy></with_attributes></news>
<news><record_title>[NEWS]:Some 1</record_title><record_content>Some content 1</record_content><extra>Some extra data</extra><with_attributes><Good_guy my-key-1="my value 1" my-key-2="my value 2"><name>Luke Skywalker</name><weapon>Lightsaber</weapon></Good_guy><Bad_guy><name><![CDATA[<h1>Sauron</h1>]]></name><weapon>Evil Eye</weapon></Bad_guy></with_attributes><with_mixed><first>line</first>
<second>line with <a href="https://example.com">some</a> html/xml tag</second>
<third>line with &amp; symbol</third></with_mixed></news>
<news><record_title>[NEWS]:Some 2</record_title><record_content>Some content 2</record_content><extra>Some extra data</extra><with_attributes><Good_guy my-key-1="my value 1" my-key-2="my value 2"><name>Luke Skywalker</name><weapon>Lightsaber</weapon></Good_guy><Bad_guy><name><![CDATA[<h1>Sauron</h1>]]></name><weapon>Evil Eye</weapon></Bad_guy></with_attributes><with_mixed><first>line</first>
<second>line with <a href="https://example.com">some</a> html/xml tag</second>
<third>line with &amp; symbol</third></with_mixed></news>
<news><record_title>[NEWS]:Some 3</record_title><record_content>Some content 3</record_content><extra>Some extra data</extra><with_attributes><Good_guy my-key-1="my value 1" my-key-2="my value 2"><name>Luke Skywalker</name><weapon>Lightsaber</weapon></Good_guy><Bad_guy><name><![CDATA[<h1>Sauron</h1>]]></name><weapon>Evil Eye</weapon></Bad_guy></with_attributes><with_mixed><first>line</first>
<second>line with <a href="https://example.com">some</a> html/xml tag</second>
<third>line with &amp; symbol</third></with_mixed></news>
</PartialFeed>
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
<weapon>Evil Eye</weapon>
</Bad_guy>
</with_attributes>
<with_mixed><first>line</first>
<second>line with <a href="https://example.com">some</a> html/xml tag</second>
<third>line with &amp; symbol</third></with_mixed>
</news>
<news>
<record_title>[NEWS]:Some 2</record_title>
Expand All @@ -29,6 +32,9 @@
<weapon>Evil Eye</weapon>
</Bad_guy>
</with_attributes>
<with_mixed><first>line</first>
<second>line with <a href="https://example.com">some</a> html/xml tag</second>
<third>line with &amp; symbol</third></with_mixed>
</news>
<news>
<record_title>[NEWS]:Some 3</record_title>
Expand All @@ -44,5 +50,8 @@
<weapon>Evil Eye</weapon>
</Bad_guy>
</with_attributes>
<with_mixed><first>line</first>
<second>line with <a href="https://example.com">some</a> html/xml tag</second>
<third>line with &amp; symbol</third></with_mixed>
</news>
</PartialFeed>
14 changes: 14 additions & 0 deletions tests/Expectations.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,17 @@

return $this;
});

expect()->pipe('toMatchSnapshot', function (Closure $next) {
if (! is_string($this->value)) {
return $this->value;
}

$this->value = preg_replace(
pattern : '/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{6}Z)/',
replacement: '2025-09-04T04:08:12.000000Z',
subject : $this->value
);

return $next();
});
29 changes: 29 additions & 0 deletions tests/Feature/Console/Generation/EnsureDeleteTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

use DragonCode\LaravelFeed\Commands\FeedGenerateCommand;
use DragonCode\LaravelFeed\Models\Feed;
use Illuminate\Filesystem\Filesystem;

use function Pest\Laravel\artisan;

test('success', function () {
$filesystem = new Filesystem;

$feed = Feed::firstOrFail();

$path = app($feed->class)->path();
$draft = app($feed->class)->path() . '.draft';

$filesystem->ensureDirectoryExists(dirname($path));

$filesystem->put($path, 'foo');
$filesystem->put($draft, 'bar');

artisan(FeedGenerateCommand::class, [
'feed' => $feed->id,
])->assertSuccessful()->run();

expect($feed)->toMatchGeneratedFeed();
});
34 changes: 34 additions & 0 deletions tests/Feature/Console/Schedule/RegisterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

use DragonCode\LaravelFeed\Helpers\ScheduleFeedHelper;
use DragonCode\LaravelFeed\Models\Feed;
use Illuminate\Console\Scheduling\Event;
use Illuminate\Support\Facades\Schedule;
use Illuminate\Support\Str;

test('cron', function () {
expect(Schedule::events())->toHaveCount(0);

app(ScheduleFeedHelper::class)->commands();

$feeds = Feed::get();

$events = collect(Schedule::events())
->mapWithKeys(function (Event $event) {
$key = Str::of($event->command)->afterLast(' ')->toInteger();
$value = $event->expression;

return [$key => $value];
})
->all();

expect($events)->toHaveCount(
$feeds->count()
);

$feeds->each(
fn (Feed $feed) => expect($events[$feed->id])->toBe($feed->expression)
);
});
14 changes: 14 additions & 0 deletions tests/Feature/Feeds/ModelTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

use Workbench\App\Data\NewsFakeData;
use Workbench\App\Feeds\ModelFeed;

test('export', function (bool $pretty) {
setPrettyXml($pretty);

createNews(...NewsFakeData::toArray());

expectFeedSnapshot(ModelFeed::class);
})->with('boolean');
2 changes: 1 addition & 1 deletion tests/Feature/Feeds/PartialTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
setPrettyXml($pretty);

createNews(static fn () => [
'updated_at' => fake()->dateTimeBetween(endDate: '-1 month'),
'updated_at' => fake()->dateTimeBetween(endDate: getDefaultDateTime()->subMonth()->toIso8601String()),
]);

createNews(...NewsFakeData::toArray());
Expand Down
29 changes: 29 additions & 0 deletions tests/Feature/Queries/Delete/SuccessTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

use DragonCode\LaravelFeed\Models\Feed;
use DragonCode\LaravelFeed\Queries\FeedQuery;

use function Pest\Laravel\assertDatabaseHas;
use function Pest\Laravel\assertDatabaseMissing;

test('success', function () {
$feed = Feed::firstOrFail();

assertDatabaseHas(Feed::class, [
'id' => $feed->id,
'deleted_at' => null,
]);

app(FeedQuery::class)->delete($feed->id);

assertDatabaseHas(Feed::class, [
'id' => $feed->id,
]);

assertDatabaseMissing(Feed::class, [
'id' => $feed->id,
'deleted_at' => null,
]);
});
Loading