Skip to content

Commit

Permalink
Add PHP 8.4 support and improve test coverage (#47) (#48)
Browse files Browse the repository at this point in the history
* Migrate config renovate.json (#46)

* Add PHP 8.4 support and improve test coverage

* Fix content-type of geostackip-script

* Add Guzzle to require-dev for HTTP client testing

* Update orchestra/testbench to version constraint to ^9.1

* Refactor PHP extensions for streamlined setup

* Remove unused ext-pcntl dependency

* Add SQLite extension for testing environment

* Remove unused curl extension from dependencies

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
  • Loading branch information
tvup and renovate[bot] authored Feb 1, 2025
1 parent ab76b2e commit a440b86
Show file tree
Hide file tree
Showing 13 changed files with 363 additions and 21 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ jobs:
- {php: 8.1, laravel: 10.*, testbench: 8.*}
- {php: 8.2, laravel: 10.*, testbench: 8.*}
- {php: 8.3, laravel: 10.*, testbench: 8.*}
- {php: 8.2, laravel: 11.*, testbench: 9.*}
- {php: 8.3, laravel: 11.*, testbench: 9.*}
- {php: 8.2, laravel: 11.*, testbench: ^9.1}
- {php: 8.3, laravel: 11.*, testbench: ^9.1}
- {php: 8.4, laravel: 11.*, testbench: ^9.1}

name: PHP ${{ matrix.php-laravel-testbench.php }} - Laravel ${{ matrix.php-laravel-testbench.laravel }} - Testbench ${{ matrix.php-laravel-testbench.testbench }} - ${{ matrix.stability }} - ${{ matrix.os }}

Expand All @@ -35,7 +36,7 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-laravel-testbench.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
extensions: mbstring, pcntl, pdo, sqlite, pdo_sqlite, gd, fileinfo
coverage: none

- name: Setup problem matchers
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ phpstan.neon.dist
testbench.yaml
vendor
node_modules
.php-cs-fixer.cache
1 change: 0 additions & 1 deletion .php-cs-fixer.cache

This file was deleted.

12 changes: 8 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,25 @@
],
"require": {
"php": "^8.0.2",
"ext-mbstring": "*",
"ext-pdo": "*",
"ext-gd": "*",
"ext-fileinfo": "*",
"laravel/framework": "^9.47|^10|^11",
"nesbot/carbon": "^2|^3",
"spatie/laravel-package-tools": "^1.16"
},
"require-dev": {
"ext-curl": "*",
"ext-sqlite3": "*",
"friendsofphp/php-cs-fixer": "^3.35",
"guzzlehttp/guzzle": "^7.0",
"larastan/larastan": "^2.4.0",
"nunomaduro/collision": "^6|^7|^8",
"orchestra/testbench": "^7|^8|^9",
"orchestra/testbench": "^7|^8|^9.1",
"pestphp/pest": "^1.22.1|^2|^3",
"pestphp/pest-plugin-laravel": "^1.4|^2|^3",
"phpstan/phpstan-phpunit": "^1.3",
"phpunit/phpunit": "^9|^10|^11",
"spatie/laravel-ray": "^1.33"
"phpunit/phpunit": "^9|^10|^11"
},
"autoload": {
"psr-4": {
Expand Down
8 changes: 6 additions & 2 deletions database/factories/IncidentFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,23 @@
use Illuminate\Support\Carbon;
use Tvup\LaravelFejlvarp\Incident;


/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<Incident>
* @extends Factory<Incident>
*/
class IncidentFactory extends Factory
{
protected $model = Incident::class;

public function definition(): array
{
$fixturePath = __DIR__ . '/../../tests/Fixtures/incident_data_command_not_found.json';
$incidentData = file_get_contents($fixturePath);

return [
'hash' => $this->faker->uuid(),
'subject' => $this->faker->sentence(),
'data' => $this->faker->optional()->randomElements(),
'data' => $this->faker->randomElements([$incidentData]),
'occurrences' => $this->faker->numberBetween(1, 100),
'last_seen_at' => Carbon::instance($this->faker->dateTime()),
'resolved_at' => null,
Expand Down
2 changes: 1 addition & 1 deletion renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"groupName": "all patch dependencies",
"groupSlug": "update-patch-dependencies",
"enabled": true,
"automerge": false,
"automerge": true,
"matchPackageNames": [
"*"
]
Expand Down
14 changes: 7 additions & 7 deletions src/Http/Controllers/Api/IncidentController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Tvup\LaravelFejlvarp\Http\Requests\IncidentStoreRequest;
use Tvup\LaravelFejlvarp\Incident;
Expand Down Expand Up @@ -66,25 +67,24 @@ public function geoip(Request $request) : Response
$seconds = 60 * 60 * 24 * 30;
$data = (array) Cache::remember('ip-' . $ip, $seconds, function () use ($ip) {
$url = 'http://api.ipstack.com/' . rawurlencode($ip) . '?access_key=' . $this->ipStackAccessKey;
$json = file_get_contents($url);
if ($json === false) {
throw new \Exception('Content of ' . $url . ' couldn\'t be parsed as json: ' . $json);
$data = Http::get($url)->json();
if ($data === []) {
throw new \Exception('Content of ' . $url . ' couldn\'t be parsed as json');
}

return json_decode($json, true);
return $data;
});
}
$response = $data ? [
'country_name' => $data['country_name'],
'region_name' => $data['region_name'],
] : null;

header('Content-Type: text/javascript');
$content = !empty($response) ? json_encode($response) : null;
if (isset($callback) && gettype($callback) == 'string') {
return response($callback . '(' . ($content ?: '{}') . ');');
return response($callback . '(' . ($content ?: '{}') . ');')->header('Content-Type', 'application/javascript');
} else {
return response($content ?: '{}');
return response($content ?: '{}')->header('Content-Type', 'application/javascript');
}
}

Expand Down
43 changes: 43 additions & 0 deletions tests/Feature/Http/Controllers/Api/IncidentControllerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Tests\Feature\Http\Controllers\Api;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use function Pest\testDirectory;
use Tvup\LaravelFejlvarp\Incident;

uses(RefreshDatabase::class);

it('will include a javascript to lookup data about the ip-address', function () {
// Arrange
$incidentData = file_get_contents(testDirectory('Fixtures/incident_data_exception.json'));
$incident = Incident::factory()->create(['resolved_at' => null, 'data' => json_decode($incidentData, true)]);

// Act
$response = $this->get(route('incident.show', $incident->hash));

// Assert
$response->assertOk();
$response->assertViewHas('incident', fn ($i) => $i->hash === $incident->hash);
$response->assertSee('/api/geoip?ip=89.150.133.237&callback=geoipCallback', false);
});

it('can fetch info about an IP-address and return as a javascript-function', function () {
// Arrange
// Set the IPStack access key to a mock key - needed for controller to enter the if-statement that fetches the IP info
config()->set('fejlvarp.ipstack.access_key', 'mock_key');

// Mock the IPStack API response
$ipStackResultOfIp = file_get_contents(testDirectory('Fixtures/ipstack_89-150-133-237.json'));
Http::fake([
'api.ipstack.com/89.150.133.237?access_key=mock_key' => Http::response(json_decode($ipStackResultOfIp, true)),
]);

// Act
$response = $this->get('/api/geoip?ip=89.150.133.237&callback=geoipCallback');

// Assert
$response->assertHeader('Content-Type', 'application/javascript');
$response->assertOk();
});
35 changes: 35 additions & 0 deletions tests/Feature/Http/Controllers/IncidentControllerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Tests\Feature\Http\Controllers;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tvup\LaravelFejlvarp\Incident;

uses(RefreshDatabase::class);

it('can retrieve all unresolved incidents', function () {
Incident::factory()->count(2)->create(['resolved_at' => null]);
Incident::factory()->create(['resolved_at' => now()]);

$response = $this->get(route('incidents.index'));

$response->assertOk();
$response->assertViewHas('incidents', fn ($incidents) => $incidents->count() === 2);
});

it('can show a single incident', function () {
$incident = Incident::factory()->create();

$response = $this->get(route('incident.show', $incident->hash));

$response->assertOk();
$response->assertViewHas('incident', fn ($i) => $i->hash === $incident->hash);
});

it('can mark an incident as resolved', function () {
$incident = Incident::factory()->create(['resolved_at' => null]);

$this->post(route('incident.delete', $incident->hash));

expect($incident->fresh()->resolved_at)->not->toBeNull();
});
108 changes: 108 additions & 0 deletions tests/Fixtures/incident_data_command_not_found.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
{
"application": "Laravel",
"error": {
"type": "Symfony\\Component\\Console\\Exception\\CommandNotFoundException",
"message": "Command \"FEJL\" is not defined.",
"code": 0,
"file": "/var/www/html/vendor/symfony/console/Application.php",
"line": 726,
"trace": "#0 /var/www/html/vendor/symfony/console/Application.php(284): Symfony\\Component\\Console\\Application->find()\n#1 /var/www/html/vendor/symfony/console/Application.php(193): Symfony\\Component\\Console\\Application->doRun()\n#2 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(198): Symfony\\Component\\Console\\Application->run()\n#3 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(1231): Illuminate\\Foundation\\Console\\Kernel->handle()\n#4 /var/www/html/artisan(13): Illuminate\\Foundation\\Application->handleCommand()\n#5 {main}"
},
"environment": {
"GET": null,
"POST": null,
"SERVER": {
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HOSTNAME": "f5408bf6ad54",
"TERM": "xterm",
"WWWUSER": "1000",
"LARAVEL_SAIL": "1",
"XDEBUG_MODE": "off",
"XDEBUG_CONFIG": "client_host=host.docker.internal",
"IGNITION_LOCAL_SITES_PATH": "/home/user/Projects/LaravelFejlVarp-parent",
"DEBIAN_FRONTEND": "noninteractive",
"TZ": "UTC",
"SUPERVISOR_PHP_COMMAND": "/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80",
"SUPERVISOR_PHP_USER": "sail",
"HOME": "/home/sail",
"PHP_SELF": "artisan",
"SCRIPT_NAME": "artisan",
"SCRIPT_FILENAME": "artisan",
"PATH_TRANSLATED": "artisan",
"DOCUMENT_ROOT": "",
"REQUEST_TIME_FLOAT": 1738366035.610871,
"REQUEST_TIME": 1738366035,
"argv": [
"artisan",
"FEJL"
],
"argc": 2,
"APP_NAME": "Laravel",
"APP_ENV": "local",
"APP_KEY": "base64:1234",
"APP_DEBUG": "true",
"APP_TIMEZONE": "UTC",
"APP_URL": "http://localhost",
"APP_PORT": "8080",
"VITE_PORT": "5173",
"APP_LOCALE": "en",
"APP_FALLBACK_LOCALE": "en",
"APP_FAKER_LOCALE": "en_US",
"APP_MAINTENANCE_DRIVER": "file",
"PHP_CLI_SERVER_WORKERS": "4",
"BCRYPT_ROUNDS": "12",
"LOG_CHANNEL": "stack",
"LOG_STACK": "single",
"LOG_DEPRECATIONS_CHANNEL": "null",
"LOG_LEVEL": "debug",
"DB_CONNECTION": "mysql",
"DB_HOST": "mysql",
"DB_PORT": "3306",
"DB_DATABASE": "laravel",
"DB_USERNAME": "sail",
"DB_PASSWORD": "password",
"FORWARD_DB_PORT": "3307",
"SESSION_DRIVER": "database",
"SESSION_LIFETIME": "120",
"SESSION_ENCRYPT": "false",
"SESSION_PATH": "/",
"SESSION_DOMAIN": "null",
"BROADCAST_CONNECTION": "log",
"FILESYSTEM_DISK": "local",
"QUEUE_CONNECTION": "database",
"CACHE_STORE": "database",
"CACHE_PREFIX": "",
"MEMCACHED_HOST": "127.0.0.1",
"REDIS_CLIENT": "phpredis",
"REDIS_HOST": "redis",
"REDIS_PASSWORD": "null",
"REDIS_PORT": "6379",
"FORWARD_REDIS_PORT": "6379",
"MAIL_MAILER": "smtp",
"MAIL_SCHEME": "null",
"MAIL_HOST": "mailpit",
"MAIL_PORT": "1025",
"MAIL_USERNAME": "null",
"MAIL_PASSWORD": "null",
"MAIL_FROM_ADDRESS": "[email protected]",
"MAIL_FROM_NAME": "Laravel",
"FORWARD_MAILPIT_PORT": "1026",
"FORWARD_MAILPIT_DASHBOARD_PORT": "8025",
"AWS_ACCESS_KEY_ID": "",
"AWS_SECRET_ACCESS_KEY": "",
"AWS_DEFAULT_REGION": "us-east-1",
"AWS_BUCKET": "",
"AWS_USE_PATH_STYLE_ENDPOINT": "false",
"VITE_APP_NAME": "Laravel",
"SCOUT_DRIVER": "meilisearch",
"MEILISEARCH_HOST": "http://meilisearch:7700",
"MEILISEARCH_NO_ANALYTICS": "false",
"FORWARD_MEILISEARCH_PORT": "7700",
"INCIDENT_MANAGER_IPSTACK_ACCESS_KEY": "access_key",
"SHELL_VERBOSITY": 0
},
"SESSION": null
},
"application_data": null,
"queries": []
}
Loading

0 comments on commit a440b86

Please sign in to comment.