Skip to content

Commit 35a22fe

Browse files
committed
upgrade to laravel 11 and require a HasRuleMessage interface for custom rules
1 parent 435c44e commit 35a22fe

File tree

11 files changed

+127
-116
lines changed

11 files changed

+127
-116
lines changed

.github/workflows/run-tests.yml

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,26 @@
11
name: run-tests
22

3-
on:
4-
push:
5-
branches: [master]
6-
pull_request:
7-
branches: [master]
3+
on: [push, pull_request]
84

95
jobs:
106
test:
11-
runs-on: ${{ matrix.os }}
7+
runs-on: ubuntu-latest
128
strategy:
139
fail-fast: true
1410
matrix:
15-
os: [ubuntu-latest, windows-latest]
16-
php: [8.1, 8.0]
17-
laravel: [9.*]
18-
stability: [prefer-lowest, prefer-stable]
11+
php: [8.3, 8.2]
12+
laravel: ["^11.0", "^10.0"]
1913
include:
20-
- laravel: 9.*
21-
testbench: 7.*
14+
- laravel: "^11.0"
15+
testbench: 9.*
16+
- laravel: "^10.0"
17+
testbench: 8.*
2218

23-
name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}
19+
name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}
2420

2521
steps:
2622
- name: Checkout code
27-
uses: actions/checkout@v3
23+
uses: actions/checkout@v4
2824

2925
- name: Setup PHP
3026
uses: shivammathur/setup-php@v2
@@ -41,7 +37,7 @@ jobs:
4137
- name: Install dependencies
4238
run: |
4339
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
44-
composer update --${{ matrix.stability }} --prefer-dist --no-interaction
40+
composer update --prefer-dist --no-interaction
4541
4642
- name: Execute tests
4743
run: vendor/bin/pest

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.idea
22
.php_cs
33
.php_cs.cache
4+
.phpunit.cache
45
.phpunit.result.cache
56
build
67
composer.lock

README.md

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,6 @@ it('throws validation error', function () {
3838
});
3939
```
4040

41-
Of course you can provide your own custom validation Rules:
42-
43-
```php
44-
it('throws validation error', function () {
45-
$this->postJson('/')
46-
->assertJsonValidationErrorRule('foo', new MyCustomRule());
47-
});
48-
```
49-
5041
It supports as well dynamic rules, such as `between`, `size`, `max` etc. You just need to specify the type of rule you want to apply:
5142

5243
```php
@@ -71,6 +62,50 @@ it('throws validation error', function () {
7162
});
7263
```
7364

65+
### Custom rules
66+
If you want to test a custom rule, make sure it implements the interface `DaniloPolani\JsonValidation\Contracts\HasRuleMessage`, needed to extract the failing message to check against.
67+
68+
For example, a custom Rule would look like this:
69+
```php
70+
<?php
71+
72+
namespace App\Rules;
73+
74+
use Closure;
75+
use DaniloPolani\JsonValidation\Contracts\HasRuleMessage;
76+
use Illuminate\Contracts\Validation\ValidationRule;
77+
78+
class Uppercase implements ValidationRule, HasRuleMessage
79+
{
80+
/**
81+
* Run the validation rule.
82+
*/
83+
public function validate(string $attribute, mixed $value, Closure $fail): void
84+
{
85+
if (strtoupper($value) !== $value) {
86+
$fail($this->message());
87+
}
88+
}
89+
90+
public function message(): string
91+
{
92+
return 'The :attribute must be uppercase.';
93+
}
94+
}
95+
```
96+
97+
And then you can use it in your assert function:
98+
99+
100+
Of course you can provide your own custom validation Rules:
101+
102+
```php
103+
it('throws validation error', function () {
104+
$this->postJson('/')
105+
->assertJsonValidationErrorRule('foo', new MyCustomRule());
106+
});
107+
```
108+
74109
## Testing
75110

76111
```bash

composer.json

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,20 @@
1616
}
1717
],
1818
"require": {
19-
"php": "^8.0",
19+
"php": "^8.2",
2020
"spatie/laravel-package-tools": "^1.9.2",
21-
"illuminate/contracts": "^9.0|^10.0",
22-
"illuminate/support": "^9.0|^10.0",
23-
"illuminate/validation": "^9.0|^10.0"
21+
"illuminate/contracts": "^10.0|^11.0",
22+
"illuminate/support": "^10.0|^11.0",
23+
"illuminate/validation": "^10.0|^11.0"
2424
},
2525
"require-dev": {
26-
"nunomaduro/collision": "^6.0",
26+
"nunomaduro/collision": "^7.0",
2727
"nunomaduro/larastan": "^2.0.1",
28-
"orchestra/testbench": "^7.0",
29-
"pestphp/pest": "^1.21",
30-
"pestphp/pest-plugin-laravel": "^1.1",
28+
"orchestra/testbench": "^8.0|^9.0",
29+
"pestphp/pest": "^2.0",
30+
"pestphp/pest-plugin-laravel": "^2.0",
3131
"phpstan/extension-installer": "^1.1",
32-
"phpstan/phpstan-deprecation-rules": "^1.0",
33-
"phpstan/phpstan-phpunit": "^1.0",
34-
"phpunit/phpunit": "^9.5",
35-
"spatie/laravel-ray": "^1.26"
32+
"phpstan/phpstan-deprecation-rules": "^1.0"
3633
},
3734
"autoload": {
3835
"psr-4": {

phpunit.xml.dist

Lines changed: 21 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,23 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<phpunit
3-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4-
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
5-
backupGlobals="false"
6-
backupStaticAttributes="false"
7-
bootstrap="vendor/autoload.php"
8-
colors="true"
9-
convertErrorsToExceptions="true"
10-
convertNoticesToExceptions="true"
11-
convertWarningsToExceptions="true"
12-
processIsolation="false"
13-
stopOnFailure="false"
14-
executionOrder="random"
15-
failOnWarning="true"
16-
failOnRisky="true"
17-
failOnEmptyTestSuite="true"
18-
beStrictAboutOutputDuringTests="true"
19-
verbose="true"
20-
>
21-
<testsuites>
22-
<testsuite name="DaniloPolani Test Suite">
23-
<directory>tests</directory>
24-
</testsuite>
25-
</testsuites>
26-
<coverage>
27-
<include>
28-
<directory suffix=".php">./src</directory>
29-
</include>
30-
<report>
31-
<html outputDirectory="build/coverage"/>
32-
<text outputFile="build/coverage.txt"/>
33-
<clover outputFile="build/logs/clover.xml"/>
34-
</report>
35-
</coverage>
36-
<logging>
37-
<junit outputFile="build/report.junit.xml"/>
38-
</logging>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" backupGlobals="false" bootstrap="vendor/autoload.php" colors="true" processIsolation="false" stopOnFailure="false" executionOrder="random" failOnWarning="true" failOnRisky="true" failOnEmptyTestSuite="true" beStrictAboutOutputDuringTests="true" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
3+
<testsuites>
4+
<testsuite name="DaniloPolani Test Suite">
5+
<directory>tests</directory>
6+
</testsuite>
7+
</testsuites>
8+
<coverage>
9+
<report>
10+
<html outputDirectory="build/coverage"/>
11+
<text outputFile="build/coverage.txt"/>
12+
<clover outputFile="build/logs/clover.xml"/>
13+
</report>
14+
</coverage>
15+
<logging>
16+
<junit outputFile="build/report.junit.xml"/>
17+
</logging>
18+
<source>
19+
<include>
20+
<directory suffix=".php">./src</directory>
21+
</include>
22+
</source>
3923
</phpunit>

src/Contracts/HasRuleMessage.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace DaniloPolani\JsonValidation\Contracts;
4+
5+
interface HasRuleMessage
6+
{
7+
public function message(): string;
8+
}

src/JsonValidation.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,15 @@
22

33
namespace DaniloPolani\JsonValidation;
44

5-
use Illuminate\Contracts\Validation\Rule as RuleContract;
5+
use DaniloPolani\JsonValidation\Contracts\HasRuleMessage;
66
use Illuminate\Support\Facades\App;
77

88
class JsonValidation
99
{
1010
/**
1111
* Get the error messages for an attribute and a validation rule.
12-
*
13-
* @param string $attribute
14-
* @param string|\Illuminate\Contracts\Validation\Rule $rule
15-
* @return array
1612
*/
17-
public static function getRuleErrorMessage(string $attribute, string|RuleContract $rule): array
13+
public static function getRuleErrorMessage(string $attribute, string|HasRuleMessage $rule): array
1814
{
1915
return (new Validator(App::make('translator'), [], []))
2016
->getErrorMessage(...func_get_args());

src/JsonValidationServiceProvider.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace DaniloPolani\JsonValidation;
44

5-
use Illuminate\Contracts\Validation\Rule as RuleContract;
5+
use DaniloPolani\JsonValidation\Contracts\HasRuleMessage;
66
use Illuminate\Support\Facades\App;
77
use Illuminate\Testing\Assert as PHPUnit;
88
use Illuminate\Testing\TestResponse;
@@ -28,7 +28,7 @@ public function packageBooted(): void
2828
* @param string $responseKey
2929
* @return self
3030
*/
31-
function (string|array $attribute, string|RuleContract|null $rule = null, string $responseKey = 'errors') {
31+
function (string|array $attribute, string|HasRuleMessage|null $rule = null, string $responseKey = 'errors') {
3232
$validationRules = $attribute;
3333

3434
if (is_string($attribute)) {

src/Validator.php

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace DaniloPolani\JsonValidation;
44

5-
use Illuminate\Contracts\Validation\Rule as RuleContract;
5+
use DaniloPolani\JsonValidation\Contracts\HasRuleMessage;
66
use Illuminate\Support\Str;
77
use Illuminate\Validation\ValidationRuleParser;
88

@@ -22,28 +22,10 @@ class Validator extends \Illuminate\Validation\Validator
2222

2323
/**
2424
* Get the error messages for an attribute and a validation rule.
25-
*
26-
* @param string $attribute
27-
* @param string|\Illuminate\Contracts\Validation\Rule $rule
28-
* @return array
2925
*/
30-
public function getErrorMessage(string $attribute, string|RuleContract $rule): array
26+
public function getErrorMessage(string $attribute, string|HasRuleMessage $rule): array
3127
{
32-
[$rule, $parameters] = ValidationRuleParser::parse($rule);
33-
$result = [];
34-
35-
// First we will get the correct keys for the given attribute in case the field is nested in
36-
// an array. Then we determine if the given rule accepts other field names as parameters.
37-
// If so, we will replace any asterisks found in the parameters with the correct keys.
38-
if ($this->dependsOnOtherFields($rule)) {
39-
$parameters = $this->replaceDotInParameters($parameters);
40-
41-
if ($keys = $this->getExplicitKeys($attribute)) {
42-
$parameters = $this->replaceAsterisksInParameters($parameters, $keys);
43-
}
44-
}
45-
46-
if ($rule instanceof RuleContract) {
28+
if ($rule instanceof HasRuleMessage) {
4729
$messages = $rule->message();
4830

4931
$messages = $messages ? (array) $messages : [get_class($rule)];
@@ -60,6 +42,20 @@ public function getErrorMessage(string $attribute, string|RuleContract $rule): a
6042
return $result;
6143
}
6244

45+
[$rule, $parameters] = ValidationRuleParser::parse($rule);
46+
$result = [];
47+
48+
// First we will get the correct keys for the given attribute in case the field is nested in
49+
// an array. Then we determine if the given rule accepts other field names as parameters.
50+
// If so, we will replace any asterisks found in the parameters with the correct keys.
51+
if ($this->dependsOnOtherFields($rule)) {
52+
$parameters = $this->replaceDotInParameters($parameters);
53+
54+
if ($keys = $this->getExplicitKeys($attribute)) {
55+
$parameters = $this->replaceAsterisksInParameters($parameters, $keys);
56+
}
57+
}
58+
6359
return [
6460
$this->buildMessage(
6561
$this->getMessage($attribute, $rule),
@@ -72,12 +68,6 @@ public function getErrorMessage(string $attribute, string|RuleContract $rule): a
7268

7369
/**
7470
* Build the validation message.
75-
*
76-
* @param string $message
77-
* @param string $attribute
78-
* @param string $rule
79-
* @param array $parameters
80-
* @return string
8171
*/
8272
protected function buildMessage(string $message, string $attribute, string $rule, array $parameters): string
8373
{

tests/TestResponseTest.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22

3-
use Illuminate\Contracts\Validation\Rule as RuleContract;
3+
use DaniloPolani\JsonValidation\Contracts\HasRuleMessage;
4+
use Illuminate\Contracts\Validation\ValidationRule;
45
use Illuminate\Http\Response;
56
use Illuminate\Testing\TestResponse;
67
use PHPUnit\Framework\ExpectationFailedException;
@@ -32,10 +33,11 @@
3233
});
3334

3435
it('accepts a custom rule', function () {
35-
$rule = new class () implements RuleContract {
36-
public function passes($attribute, $value): bool
36+
$rule = new class() implements ValidationRule, HasRuleMessage
37+
{
38+
public function validate(string $attribute, mixed $value, \Closure $fail): void
3739
{
38-
return true;
40+
return;
3941
}
4042

4143
public function message(): string

0 commit comments

Comments
 (0)