diff --git a/tests/Feature/Automation/FeedInspectionTest.php b/tests/Feature/Automation/FeedInspectionTest.php
index 7d31baed..c5ab6d00 100644
--- a/tests/Feature/Automation/FeedInspectionTest.php
+++ b/tests/Feature/Automation/FeedInspectionTest.php
@@ -16,7 +16,7 @@
});
it('returns the discovered fields for a feed', function () {
- Http::fake(['1.1.1.1/*' => Http::response(file_get_contents(base_path('tests/fixtures/feeds/youtube_atom.xml')), 200)]);
+ Http::fake(['1.1.1.1/*' => Http::response(feedFixture('youtube_atom'), 200)]);
$automation = Automation::factory()->for($this->workspace)->create();
@@ -35,7 +35,7 @@
});
it('resolves workspace variables in the feed url before fetching', function () {
- Http::fake(['1.1.1.1/*' => Http::response(file_get_contents(base_path('tests/fixtures/feeds/youtube_atom.xml')), 200)]);
+ Http::fake(['1.1.1.1/*' => Http::response(feedFixture('youtube_atom'), 200)]);
$automation = Automation::factory()->for($this->workspace)->create([
'variables' => [['key' => 'HOST', 'value' => '1.1.1.1']],
diff --git a/tests/Feature/Automation/Node/FetchRssNodeTest.php b/tests/Feature/Automation/Node/FetchRssNodeTest.php
index f915098e..dc83b8e3 100644
--- a/tests/Feature/Automation/Node/FetchRssNodeTest.php
+++ b/tests/Feature/Automation/Node/FetchRssNodeTest.php
@@ -15,37 +15,11 @@
afterEach(fn () => Carbon::setTestNow());
-const FETCH_RSS_OLD = <<<'XML'
-
-
- - Ancienthttps://1.1.1.1/11Mon, 01 Jan 2024 12:00:00 +0000
- - Oldhttps://1.1.1.1/22Sat, 01 Feb 2025 12:00:00 +0000
-
-XML;
-
-const FETCH_RSS_MIXED = <<<'XML'
-
-
- - Olderhttps://1.1.1.1/aaSat, 01 Feb 2025 12:00:00 +0000
- - Newer1https://1.1.1.1/bbSun, 01 Jun 2025 12:00:00 +0000
- - Newer2https://1.1.1.1/ccSun, 15 Jun 2025 12:00:00 +0000
-
-XML;
-
-const FETCH_RSS_THREE_NEW = <<<'XML'
-
-
- - New1https://1.1.1.1/xxSun, 01 Jun 2025 12:00:00 +0000
- - New2https://1.1.1.1/yyMon, 02 Jun 2025 12:00:00 +0000
- - New3https://1.1.1.1/zzTue, 03 Jun 2025 12:00:00 +0000
-
-XML;
-
beforeEach(fn () => Bus::fake());
it('first execution dispatches nothing and stores watermark from newest item', function () {
Carbon::setTestNow('2026-01-15 10:00:00');
- Http::fake(['1.1.1.1/*' => Http::response(FETCH_RSS_OLD, 200)]);
+ Http::fake(['1.1.1.1/*' => Http::response(feedFixture('rss_old'), 200)]);
$automation = Automation::factory()->active()->create([
'nodes' => [
@@ -74,7 +48,7 @@
it('processes the first new item on the current run and spawns siblings for the rest', function () {
Carbon::setTestNow('2026-01-15 10:00:00');
- Http::fake(['1.1.1.1/*' => Http::response(FETCH_RSS_MIXED, 200)]);
+ Http::fake(['1.1.1.1/*' => Http::response(feedFixture('rss_mixed'), 200)]);
$automation = Automation::factory()->active()->create([
'nodes' => [
@@ -111,7 +85,7 @@
it('spawns sibling runs down the item edge for each remaining new item', function () {
Carbon::setTestNow('2026-01-15 10:00:00');
- Http::fake(['1.1.1.1/*' => Http::response(FETCH_RSS_THREE_NEW, 200)]);
+ Http::fake(['1.1.1.1/*' => Http::response(feedFixture('rss_three_new'), 200)]);
$automation = Automation::factory()->active()->create([
'nodes' => [
@@ -151,7 +125,7 @@
it('fans every spawned item out across all branches wired to the fetch node', function () {
Carbon::setTestNow('2026-01-15 10:00:00');
- Http::fake(['1.1.1.1/*' => Http::response(FETCH_RSS_THREE_NEW, 200)]);
+ Http::fake(['1.1.1.1/*' => Http::response(feedFixture('rss_three_new'), 200)]);
$automation = Automation::factory()->active()->create([
'nodes' => [
@@ -185,7 +159,7 @@
it('does not persist the production watermark on a manual real-data test', function () {
Carbon::setTestNow('2026-01-15 10:00:00');
- Http::fake(['1.1.1.1/*' => Http::response(FETCH_RSS_MIXED, 200)]);
+ Http::fake(['1.1.1.1/*' => Http::response(feedFixture('rss_mixed'), 200)]);
$automation = Automation::factory()->active()->create([
'nodes' => [
@@ -226,7 +200,7 @@
it('advances the production watermark on a non-manual real-data run', function () {
Carbon::setTestNow('2026-01-15 10:00:00');
- Http::fake(['1.1.1.1/*' => Http::response(FETCH_RSS_MIXED, 200)]);
+ Http::fake(['1.1.1.1/*' => Http::response(feedFixture('rss_mixed'), 200)]);
$automation = Automation::factory()->active()->create([
'nodes' => [
@@ -261,7 +235,7 @@
it('processes an Atom feed (YouTube) that the old RSS-only parser dropped', function () {
Carbon::setTestNow('2026-06-16 10:00:00');
- Http::fake(['1.1.1.1/*' => Http::response(file_get_contents(base_path('tests/fixtures/feeds/youtube_atom.xml')), 200)]);
+ Http::fake(['1.1.1.1/*' => Http::response(feedFixture('youtube_atom'), 200)]);
$automation = Automation::factory()->active()->create();
@@ -317,14 +291,7 @@
it('skips items without a publish date', function () {
Carbon::setTestNow('2026-01-15 10:00:00');
- $feed = <<<'XML'
-
-
- - Datedhttps://1.1.1.1/ddSun, 01 Jun 2025 12:00:00 +0000
- - NoDatehttps://1.1.1.1/nn
-
- XML;
- Http::fake(['1.1.1.1/*' => Http::response($feed, 200)]);
+ Http::fake(['1.1.1.1/*' => Http::response(feedFixture('rss_dateless'), 200)]);
$automation = Automation::factory()->active()->create();
AutomationNodeState::create([
@@ -343,13 +310,7 @@
it('falls back to the link as the dedup key when an item has no guid', function () {
Carbon::setTestNow('2026-01-15 10:00:00');
- $feed = <<<'XML'
-
-
- - LinkKeyhttps://1.1.1.1/only-linkSun, 01 Jun 2025 12:00:00 +0000
-
- XML;
- Http::fake(['1.1.1.1/*' => Http::response($feed, 200)]);
+ Http::fake(['1.1.1.1/*' => Http::response(feedFixture('rss_no_guid'), 200)]);
$automation = Automation::factory()->active()->create();
AutomationNodeState::create([
diff --git a/tests/Pest.php b/tests/Pest.php
index 373a3c94..523a1605 100644
--- a/tests/Pest.php
+++ b/tests/Pest.php
@@ -103,3 +103,8 @@ function createApiTestToken(array $overrides = []): array
'user' => $user,
];
}
+
+function feedFixture(string $name): string
+{
+ return file_get_contents(base_path("tests/fixtures/feeds/{$name}.xml"));
+}
diff --git a/tests/Unit/Automation/FeedParserTest.php b/tests/Unit/Automation/FeedParserTest.php
index d12e948d..cda1a74b 100644
--- a/tests/Unit/Automation/FeedParserTest.php
+++ b/tests/Unit/Automation/FeedParserTest.php
@@ -4,11 +4,6 @@
use App\Services\Automation\FeedParser;
-function feedFixture(string $name): string
-{
- return file_get_contents(base_path("tests/fixtures/feeds/{$name}.xml"));
-}
-
beforeEach(function () {
$this->parser = new FeedParser;
});
diff --git a/tests/fixtures/feeds/rss_dateless.xml b/tests/fixtures/feeds/rss_dateless.xml
new file mode 100644
index 00000000..354740d3
--- /dev/null
+++ b/tests/fixtures/feeds/rss_dateless.xml
@@ -0,0 +1,5 @@
+
+
+ - Datedhttps://1.1.1.1/ddSun, 01 Jun 2025 12:00:00 +0000
+ - NoDatehttps://1.1.1.1/nn
+
diff --git a/tests/fixtures/feeds/rss_mixed.xml b/tests/fixtures/feeds/rss_mixed.xml
new file mode 100644
index 00000000..e0ff0f35
--- /dev/null
+++ b/tests/fixtures/feeds/rss_mixed.xml
@@ -0,0 +1,6 @@
+
+
+ - Olderhttps://1.1.1.1/aaSat, 01 Feb 2025 12:00:00 +0000
+ - Newer1https://1.1.1.1/bbSun, 01 Jun 2025 12:00:00 +0000
+ - Newer2https://1.1.1.1/ccSun, 15 Jun 2025 12:00:00 +0000
+
diff --git a/tests/fixtures/feeds/rss_no_guid.xml b/tests/fixtures/feeds/rss_no_guid.xml
new file mode 100644
index 00000000..50da87ed
--- /dev/null
+++ b/tests/fixtures/feeds/rss_no_guid.xml
@@ -0,0 +1,4 @@
+
+
+ - LinkKeyhttps://1.1.1.1/only-linkSun, 01 Jun 2025 12:00:00 +0000
+
diff --git a/tests/fixtures/feeds/rss_old.xml b/tests/fixtures/feeds/rss_old.xml
new file mode 100644
index 00000000..89742385
--- /dev/null
+++ b/tests/fixtures/feeds/rss_old.xml
@@ -0,0 +1,5 @@
+
+
+ - Ancienthttps://1.1.1.1/11Mon, 01 Jan 2024 12:00:00 +0000
+ - Oldhttps://1.1.1.1/22Sat, 01 Feb 2025 12:00:00 +0000
+
diff --git a/tests/fixtures/feeds/rss_three_new.xml b/tests/fixtures/feeds/rss_three_new.xml
new file mode 100644
index 00000000..6d44e06d
--- /dev/null
+++ b/tests/fixtures/feeds/rss_three_new.xml
@@ -0,0 +1,6 @@
+
+
+ - New1https://1.1.1.1/xxSun, 01 Jun 2025 12:00:00 +0000
+ - New2https://1.1.1.1/yyMon, 02 Jun 2025 12:00:00 +0000
+ - New3https://1.1.1.1/zzTue, 03 Jun 2025 12:00:00 +0000
+