diff --git a/Tests/ArchTest.php b/Tests/ArchTest.php
new file mode 100644
index 0000000..e5be658
--- /dev/null
+++ b/Tests/ArchTest.php
@@ -0,0 +1,5 @@
+expect(['dd', 'dump', 'ray'])
+ ->each->not->toBeUsed();
\ No newline at end of file
diff --git a/Tests/CisionTest.php b/Tests/CisionTest.php
new file mode 100644
index 0000000..8cdb18b
--- /dev/null
+++ b/Tests/CisionTest.php
@@ -0,0 +1,34 @@
+ Http::response(file_get_contents(__DIR__.'/Fixtures/rss-press.xml')),
+ ]);
+
+ $cision = new Cision('test-company');
+ $data = $cision->press();
+
+ expect($data)->toBeArray();
+ expect($data)->toHaveKey('items');
+ expect($data['items'])->not->toBeEmpty();
+
+ $item = $data['items'][0];
+ expect($item)->toHaveKeys(['guid', 'title', 'description', 'link', 'created_at']);
+});
+
+it('can fetch and parse full article content', function () {
+ Http::fake([
+ 'news.cision.com/*' => Http::response(file_get_contents(__DIR__.'/Fixtures/article.html')),
+ ]);
+
+ $cision = new Cision();
+ $content = $cision->fetchContent('https://news.cision.com/se/example/r/test,c123456');
+
+ expect($content)->toHaveKeys(['header', 'published_at', 'content']);
+ expect($content['header'])->not->toBeEmpty();
+ expect($content['content'])->toContain('
+
+
Test Article Header
+
+
Lead: This is a test article paragraph.
+
Italic sentence.
+
+
+
diff --git a/Tests/Fixtures/rss-press.xml b/Tests/Fixtures/rss-press.xml
new file mode 100644
index 0000000..857c9be
--- /dev/null
+++ b/Tests/Fixtures/rss-press.xml
@@ -0,0 +1,13 @@
+
+
+
+ Test Press Releases
+ -
+ test-guid
+ Test Press Title
+ This is a test press release description.
+ https://news.cision.com/se/example/r/test,c123456
+ Fri, 04 Jul 2025 07:55:00 GMT
+
+
+
diff --git a/Tests/Pest.php b/Tests/Pest.php
new file mode 100644
index 0000000..45c3e5c
--- /dev/null
+++ b/Tests/Pest.php
@@ -0,0 +1,5 @@
+in(__DIR__);
\ No newline at end of file
diff --git a/Tests/TestCase.php b/Tests/TestCase.php
new file mode 100644
index 0000000..7d25c9e
--- /dev/null
+++ b/Tests/TestCase.php
@@ -0,0 +1,37 @@
+ 'Mattitja\\Cision\\Database\\Factories\\'.class_basename($modelName).'Factory'
+ );
+ }
+
+ protected function getPackageProviders($app)
+ {
+ return [
+ CisionServiceProvider::class,
+ ];
+ }
+
+ public function getEnvironmentSetUp($app)
+ {
+ config()->set('database.default', 'testing');
+
+ /*
+ foreach (\Illuminate\Support\Facades\File::allFiles(__DIR__ . '/database/migrations') as $migration) {
+ (include $migration->getRealPath())->up();
+ }
+ */
+ }
+}
\ No newline at end of file
diff --git a/src/Cision.php b/src/Cision.php
index 430c1bc..1bff21f 100755
--- a/src/Cision.php
+++ b/src/Cision.php
@@ -114,30 +114,41 @@ class Cision
return false;
}
+ // Suppress XML parsing warnings
+ libxml_use_internal_errors(true);
$xml = simplexml_load_string($data, "SimpleXMLElement", LIBXML_NOCDATA);
+ libxml_clear_errors();
+
if ($xml === false) {
return false;
}
+ // Convert XML to JSON then to array
$json = json_encode($xml);
$rows = json_decode($json, true);
+ // Validate structure
if (!isset($rows['channel']['item'])) {
return false;
}
- $items = array_map(fn ($item) => [
+ // Ensure 'item' is always an array
+ $items = $rows['channel']['item'];
+ $items = isset($items[0]) ? $items : [$items];
+
+ // Format the result
+ $formatted = array_map(fn ($item) => [
'guid' => $item['guid'],
'title' => $item['title'],
'description' => $item['description'],
'link' => $item['link'],
'created_at' => Carbon::parse($item['pubDate'])->addHours(2)->format('Y-m-d H:i:s'),
- ], $rows['channel']['item']);
+ ], $items);
return [
- 'items' => $items,
+ 'items' => $formatted,
'previous_page' => $page > 1 ? $page - 1 : false,
- 'next_page' => count($items) === 24 ? $page + 1 : false,
+ 'next_page' => count($formatted) === 24 ? $page + 1 : false,
];
}
}