Fix packaging, timezone handling and HTML cleaning bugs
Fix PHP code style issues / php-code-styling (push) Waiting to run
PHPStan / phpstan (push) Waiting to run
run-tests / P8.3 - L11.* - prefer-lowest - ubuntu-latest (push) Waiting to run
run-tests / P8.3 - L11.* - prefer-stable - ubuntu-latest (push) Waiting to run
run-tests / P8.4 - L11.* - prefer-lowest - ubuntu-latest (push) Waiting to run
run-tests / P8.4 - L11.* - prefer-stable - ubuntu-latest (push) Waiting to run
run-tests / P8.3 - L12.* - prefer-lowest - ubuntu-latest (push) Waiting to run
run-tests / P8.3 - L12.* - prefer-stable - ubuntu-latest (push) Waiting to run
run-tests / P8.4 - L12.* - prefer-lowest - ubuntu-latest (push) Waiting to run
run-tests / P8.4 - L12.* - prefer-stable - ubuntu-latest (push) Waiting to run
dependabot-auto-merge / dependabot (pull_request_target) Skipped

- Replace symfony 7.4.x-dev constraints with stable ranges so the
  package installs with minimum-stability stable
- Add the Cision facade referenced in composer.json and a config file
  (slug, timezone); the constructor now falls back to config('cision.slug')
- Convert feed timestamps with a real timezone instead of a hardcoded +2h,
  which was off by an hour during winter time
- Return false from fetchContent() when the request fails or the page
  has no article/heading, instead of throwing
- Fix italic paragraph detection, which never matched
- Fix literal '\n' in HtmlCleaner whitespace cleanup
- Normalize empty feed elements to empty strings
- Update README and add tests for the above
This commit is contained in:
mathiaspalmqvist committed 2026-11-11 20:37:05 +01:00
1 parent f9487a3336
commit 392aec8529
9 files changed
+207 -28

No files matched your search

+74
View File
@@ -31,3 +31,77 @@ it('can fetch and parse full article content', function () {
expect($content['header'])->not->toBeEmpty();
expect($content['content'])->toContain('<p');
});
it('converts feed timestamps to Stockholm time in summer and winter', function () {
$rss = fn (string $date) => <<<XML
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0"><channel>
<item><guid>a</guid><title>A</title><description>D</description><link>L</link><pubDate>{$date}</pubDate></item>
</channel></rss>
XML;
Http::fakeSequence()
->push($rss('Fri, 04 Jul 2025 07:55:00 GMT'))
->push($rss('Wed, 15 Jan 2025 07:55:00 GMT'));
$cision = new Cision('test-company');
expect($cision->press()['items'][0]['created_at'])->toBe('2025-07-04 09:55:00');
expect($cision->press()['items'][0]['created_at'])->toBe('2025-01-15 08:55:00');
});
it('returns empty strings for empty feed elements', function () {
Http::fake([
'news.cision.com/*' => Http::response(<<<'XML'
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0"><channel>
<item><guid>a</guid><title>A</title><description></description><link>L</link><pubDate>Fri, 04 Jul 2025 07:55:00 GMT</pubDate></item>
</channel></rss>
XML),
]);
expect((new Cision('test-company'))->press()['items'][0]['description'])->toBe('');
});
it('returns false when the feed request fails', function () {
Http::fake(['news.cision.com/*' => Http::response('', 500)]);
expect((new Cision('test-company'))->press())->toBeFalse();
});
it('returns false when the article request fails', function () {
Http::fake(['news.cision.com/*' => Http::response('', 404)]);
expect((new Cision('test-company'))->fetchContent('https://news.cision.com/se/x'))->toBeFalse();
});
it('returns false when the page has no article', function () {
Http::fake(['news.cision.com/*' => Http::response('<html><body><p>Nope</p></body></html>')]);
expect((new Cision('test-company'))->fetchContent('https://news.cision.com/se/x'))->toBeFalse();
});
it('marks paragraphs that start with italic text', function () {
Http::fake([
'news.cision.com/*' => Http::response(file_get_contents(__DIR__.'/Fixtures/article.html')),
]);
$content = (new Cision('test-company'))->fetchContent('https://news.cision.com/se/x')['content'];
expect($content)
->toContain('<p class="italic"><em>Italic sentence.</em></p>')
->toContain('<p><strong>Lead:</strong> This is a test article paragraph.</p>')
->not->toContain('Test Article Header');
});
it('uses the configured slug when none is given', function () {
config()->set('cision.slug', 'configured-company');
Http::fake([
'news.cision.com/*' => Http::response(file_get_contents(__DIR__.'/Fixtures/rss-press.xml')),
]);
Mattitja\Cision\Facades\Cision::press();
Http::assertSent(fn ($request) => str_contains($request->url(), 'n=configured-company'));
});