Skip to content

Commit 03e24d7

Browse files
authored
⬆️ Support Nova 5 (#5)
* 🔨 Simplify Docker Setup * ⬆️ Require Nova 5 - Laravel ^10.34 or 11.* * 👷Update CI Test Matrix For Nova 5 * 👽️ Update Lens Request to match Nova 5 Signature * 👽️ Update Action Response Assertions and Tests to handle change in Nova 5 * 📝 Update installation notes for Nova 4 * ✨ Add assertion to open in new tab with specific path
1 parent e42f237 commit 03e24d7

File tree

10 files changed

+108
-56
lines changed

10 files changed

+108
-56
lines changed

.docker/Dockerfile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM phpdockerio/php:8.4-fpm
2+
WORKDIR "/srv"
3+
4+
# Update and install necessary packages
5+
RUN apt-get update \
6+
&& apt-get -y --no-install-recommends install \
7+
git \
8+
php8.4-xdebug \
9+
sqlite3 \
10+
libsqlite3-dev \
11+
php8.4-sqlite3 \
12+
php8.4-pdo \
13+
&& apt-get clean \
14+
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
15+
16+
# Create a composer user and group
17+
RUN addgroup --gid 2000 composer && \
18+
adduser --disabled-password --ingroup composer --uid 2000 composer

.docker/php.development.dockerfile

Lines changed: 0 additions & 13 deletions
This file was deleted.

.docker/xdebug.ini

Lines changed: 0 additions & 4 deletions
This file was deleted.

.github/workflows/ci.yml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,19 @@ jobs:
1717
strategy:
1818
fail-fast: true
1919
matrix:
20-
php: ['8.0', '8.1', '8.2']
21-
laravel: [ '8.*', '9.*', '10.*', '11.*' ]
20+
php: [ '8.1', '8.2', '8.3', '8.4']
21+
laravel: [ '10.*', '11.*' ]
2222
dependency-version: [ prefer-stable ]
2323
include:
2424
- laravel: 10.*
2525
testbench: 8.*
26-
- laravel: 9.*
27-
testbench: 7.*
28-
- laravel: 8.*
29-
testbench: 6.*
3026
- laravel: 11.*
3127
testbench: 9.*
3228
exclude:
3329
- laravel: 10.*
3430
php: 8.0
31+
- laravel: 10.*
32+
php: 8.1
3533
- laravel: 11.*
3634
php: 8.1
3735
- laravel: 11.*

README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,25 @@ You can install the package in your Laravel Project via composer:
1717
composer require --dev quotevelocity/novaunit
1818
```
1919

20-
### Requirements
20+
### General Requirements
2121

2222
* PHP 8.0 or higher
2323
* [Laravel](https://laravel.com/) 9.x - 11.x
2424
* [Laravel Nova](https://nova.laravel.com/) 4.x or higher
2525
* [PHPUnit](https://github.com/sebastianbergmann/phpunit) 9.x - 11.x
2626

27-
Note: For older projects (Laravel < 9, Nova 2 or 3) please see the legacy project: [`joshgaber/novaunit`](https://github.com/joshgaber/NovaUnit) instead.
27+
28+
### Nova 4
29+
30+
As there were some breaking changes in Nova 4 to Nova 5, you should select the 4.x version of NovaUnit:
31+
32+
```sh
33+
composer require --dev quotevelocity/novaunit:4.*
34+
```
35+
36+
## Nova < 4
37+
38+
For older projects (Laravel < 9, Nova 2 or 3) please see the legacy project: [`joshgaber/novaunit`](https://github.com/joshgaber/NovaUnit) instead.
2839

2940
## Usage
3041

composer.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,17 @@
2424
}
2525
],
2626
"require": {
27-
"php": "^8.0|^8.1|^8.2",
27+
"php": "^8.1|^8.2|^8.3|^8.4",
2828
"ext-mbstring": "*",
2929
"cakephp/chronos": ">=2.0.0",
30-
"illuminate/support": "^8.83.4|^9.3.1|^10.0|^11.0",
31-
"laravel/nova": "^4.0",
32-
"phpunit/phpunit": "^9.0|^10.0|^11.0"
30+
"illuminate/support": "^10.34|^11.0",
31+
"illuminate/testing": "^10.34|^11.0",
32+
"laravel/nova": "^5.0",
33+
"phpunit/phpunit": "^10.0|^11.0"
3334
},
3435
"require-dev": {
3536
"friendsofphp/php-cs-fixer": "^3.0",
36-
"orchestra/testbench": "^6.0|^8.0|^9.0"
37+
"orchestra/testbench": "^8.0|^9.0"
3738
},
3839
"repositories": [
3940
{

docker-compose.yml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,17 @@ name: "novaunit"
22

33
services:
44
php:
5-
build:
6-
context: .docker
7-
dockerfile: php.development.dockerfile
5+
build: .docker
86
restart: unless-stopped
97
working_dir: /srv
108
volumes:
119
- .:/srv
1210
- ~/.composer:/home/composer/.composer
1311
- ./vendor:/srv/vendor:delegated
1412
- ./storage/xdebug:/tmp/xdebug:delegated
15-
- ./.docker/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini
1613
environment:
1714
XDEBUG_MODE: '${XDEBUG_MODE:-off}'
1815
XDEBUG_CONFIG: '${XDEBUG_CONFIG:-client_host=host.docker.internal}'
19-
16+
extra_hosts:
17+
- "host.docker.internal:host-gateway"
2018

src/Actions/MockActionResponse.php

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
namespace JoshGaber\NovaUnit\Actions;
44

5+
use Illuminate\Testing\Constraints\ArraySubset;
56
use JoshGaber\NovaUnit\Constraints\IsActionResponseType;
67
use Laravel\Nova\Actions\ActionResponse;
8+
use Laravel\Nova\Actions\Responses\Visit;
79
use PHPUnit\Framework\Assert as PHPUnit;
10+
use PHPUnit\Framework\AssertionFailedError;
811
use PHPUnit\Framework\Constraint\IsInstanceOf;
912
use PHPUnit\Framework\Constraint\IsType;
1013

@@ -43,7 +46,7 @@ public function assertResponseType(string $type, string $message = ''): self
4346
/**
4447
* Asserts the handle response is of type "message".
4548
*
46-
* @param string $message
49+
* @param string $message
4750
* @return $this
4851
*/
4952
public function assertMessage(string $message = ''): self
@@ -65,7 +68,7 @@ public function assertDanger(string $message = ''): self
6568
/**
6669
* Asserts the handle response is of type "deleted".
6770
*
68-
* @param string $message
71+
* @param string $message
6972
* @return $this
7073
*/
7174
public function assertDeleted(string $message = ''): self
@@ -98,7 +101,7 @@ public function assertPush(string $message = ''): self
98101
/**
99102
* Asserts the handle response is of type "visit".
100103
*
101-
* @param string|null $path
104+
* @param string $path
102105
* @param array $options
103106
* @return $this
104107
*/
@@ -108,35 +111,54 @@ public function assertVisit(string $path = '', array $options = []): self
108111
return $this->assertResponseType('visit');
109112
}
110113

111-
return $this->assertResponseContainsArray(['path' => $path, 'options' => array_values($options)], 'visit');
114+
PHPUnit::assertArrayHasKey('visit', $this->response);
115+
116+
$visit = $this->response['visit'];
117+
118+
PHPUnit::logicalAnd(
119+
PHPUnit::assertNotEmpty($visit),
120+
PHPUnit::assertInstanceOf(Visit::class, $visit),
121+
PHPUnit::assertEquals($options, $visit->options),
122+
PHPUnit::assertEquals($path, $visit->path),
123+
);
124+
125+
return $this;
112126
}
113127

114128
/**
115129
* Asserts the handle response is of type "openInNewTab".
116130
*
117-
* @param string $message
131+
* @param string $message
118132
* @return $this
119133
*/
120134
public function assertOpenInNewTab(string $message = ''): self
121135
{
122-
return $this->assertResponseType('openInNewTab', $message);
136+
return $this->assertResponseContainsArray(['openInNewTab' => true], 'redirect', $message);
137+
}
138+
139+
/**
140+
* Asserts the handle response of type "openInNewTab" directs to the specified path.
141+
*/
142+
public function assertOpenInNewTabToPath(string $path, string $message = ''): self
143+
{
144+
return $this->assertResponseContainsArray(['url' => $path, 'openInNewTab' => true], 'redirect', $message);
123145
}
124146

125147
/**
126148
* Asserts the handle response is of type "download".
127149
*
128-
* @param string $message
150+
* @param string $message
129151
* @return $this
130152
*/
131153
public function assertDownload(string $message = ''): self
132154
{
133155
return $this->assertResponseType('download', $message);
134156
}
135157

136-
private function assertResponseContains(string $contents, string $type, string $message = ''): self
158+
private function assertResponseKeyContains(string $contents, string $type, string $key, string $message = ''): self
137159
{
138160
PHPUnit::assertThat(
139-
$this->response[$type] ?? '',
161+
$this->response[$type]?->{$key} ?? '',
140162
PHPUnit::logicalAnd(
141163
PHPUnit::logicalNot(PHPUnit::isEmpty()),
142164
PHPUnit::stringContains($contents, true)
@@ -150,10 +172,10 @@ private function assertResponseContains(string $contents, string $type, string $
150172
private function assertResponseContainsArray(array $contents, string $type, string $message = ''): self
151173
{
152174
PHPUnit::assertThat(
153-
$this->response[$type] ?? '',
175+
$this->response[$type]?->jsonSerialize() ?? throw new AssertionFailedError(),
154176
PHPUnit::logicalAnd(
155177
PHPUnit::logicalNot(PHPUnit::isEmpty()),
156-
PHPUnit::equalTo($contents)
178+
new ArraySubset($contents, false)
157179
),
158180
$message
159181
);
@@ -164,25 +186,25 @@ private function assertResponseContainsArray(array $contents, string $type, stri
164186
/**
165187
* Asserts the handle response is a "message" and contains the given text.
166188
*
167-
* @param string $contents The text to assert is in the response
168-
* @param string $message
189+
* @param string $contents The text to assert is in the response
190+
* @param string $message
169191
* @return $this
170192
*/
171193
public function assertMessageContains(string $contents, string $message = ''): self
172194
{
173-
return $this->assertResponseContains($contents, 'message', $message);
195+
return $this->assertResponseKeyContains($contents, 'message', 'text', $message);
174196
}
175197

176198
/**
177199
* Asserts the handle response is a "danger" and contains the given text.
178200
*
179-
* @param string $contents The text to assert is in the response
180-
* @param string $message
201+
* @param string $contents The text to assert is in the response
202+
* @param string $message
181203
* @return $this
182204
*/
183205
public function assertDangerContains(string $contents, string $message = ''): self
184206
{
185-
return $this->assertResponseContains($contents, 'danger', $message);
207+
return $this->assertResponseKeyContains($contents, 'danger', 'text', $message);
186208
}
187209

188210
/**

src/Lenses/MockLensRequest.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
namespace JoshGaber\NovaUnit\Lenses;
44

5+
use Illuminate\Contracts\Database\Eloquent\Builder;
56
use Laravel\Nova\Http\Requests\LensRequest;
67

78
class MockLensRequest extends LensRequest
89
{
9-
public $withFilters;
10-
public $withOrdering;
10+
public bool $withFilters;
11+
public bool $withOrdering;
1112

1213
public function __construct(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null)
1314
{
@@ -17,14 +18,14 @@ public function __construct(array $query = [], array $request = [], array $attri
1718
$this->withOrdering = false;
1819
}
1920

20-
public function withFilters($query)
21+
public function withFilters(Builder $query): Builder
2122
{
2223
$this->withFilters = true;
2324

2425
return $query;
2526
}
2627

27-
public function withOrdering($query, $defaultCallback = null)
28+
public function withOrdering(Builder $query, $defaultCallback = null): Builder
2829
{
2930
$this->withOrdering = true;
3031

tests/Feature/Actions/MockActionResponseTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,26 @@ public function testItSucceedsOnOpenInNewTabResponse()
113113
$mockActionResponse->assertOpenInNewTab();
114114
}
115115

116+
public function testItSucceedsOnOpenInNewTabResponseWithPath()
117+
{
118+
$mockActionResponse = new MockActionResponse(Action::openInNewTab('/test/path'));
119+
$mockActionResponse->assertOpenInNewTabToPath('/test/path');
120+
}
121+
122+
public function testItFailsOnOpenInNewTabResponseWithPathIncorrect()
123+
{
124+
$this->shouldFail();
125+
$mockActionResponse = new MockActionResponse(Action::openInNewTab('/test/path'));
126+
$mockActionResponse->assertOpenInNewTabToPath('/test/wrongpath');
127+
}
128+
129+
public function testItFailsOnOpenInNewTabResponseWithWrongAction()
130+
{
131+
$this->shouldFail();
132+
$mockActionResponse = new MockActionResponse(Action::visit('/test/path'));
133+
$mockActionResponse->assertOpenInNewTabToPath('/test/wrongpath');
134+
}
135+
116136
public function testItFailsOnResponseOtherThanOpenInNewTab()
117137
{
118138
$this->shouldFail();

0 commit comments

Comments
 (0)