Skip to content

Commit

Permalink
⬆️ Support Nova 5 (#5)
Browse files Browse the repository at this point in the history
* 🔨 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
  • Loading branch information
robertmarney authored Feb 6, 2025
1 parent e42f237 commit 03e24d7
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 56 deletions.
18 changes: 18 additions & 0 deletions .docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM phpdockerio/php:8.4-fpm
WORKDIR "/srv"

# Update and install necessary packages
RUN apt-get update \
&& apt-get -y --no-install-recommends install \
git \
php8.4-xdebug \
sqlite3 \
libsqlite3-dev \
php8.4-sqlite3 \
php8.4-pdo \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*

# Create a composer user and group
RUN addgroup --gid 2000 composer && \
adduser --disabled-password --ingroup composer --uid 2000 composer
13 changes: 0 additions & 13 deletions .docker/php.development.dockerfile

This file was deleted.

4 changes: 0 additions & 4 deletions .docker/xdebug.ini

This file was deleted.

10 changes: 4 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,19 @@ jobs:
strategy:
fail-fast: true
matrix:
php: ['8.0', '8.1', '8.2']
laravel: [ '8.*', '9.*', '10.*', '11.*' ]
php: [ '8.1', '8.2', '8.3', '8.4']
laravel: [ '10.*', '11.*' ]
dependency-version: [ prefer-stable ]
include:
- laravel: 10.*
testbench: 8.*
- laravel: 9.*
testbench: 7.*
- laravel: 8.*
testbench: 6.*
- laravel: 11.*
testbench: 9.*
exclude:
- laravel: 10.*
php: 8.0
- laravel: 10.*
php: 8.1
- laravel: 11.*
php: 8.1
- laravel: 11.*
Expand Down
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,25 @@ You can install the package in your Laravel Project via composer:
composer require --dev quotevelocity/novaunit
```

### Requirements
### General Requirements

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

Note: For older projects (Laravel < 9, Nova 2 or 3) please see the legacy project: [`joshgaber/novaunit`](https://github.com/joshgaber/NovaUnit) instead.

### Nova 4

As there were some breaking changes in Nova 4 to Nova 5, you should select the 4.x version of NovaUnit:

```sh
composer require --dev quotevelocity/novaunit:4.*
```

## Nova < 4

For older projects (Laravel < 9, Nova 2 or 3) please see the legacy project: [`joshgaber/novaunit`](https://github.com/joshgaber/NovaUnit) instead.

## Usage

Expand Down
11 changes: 6 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,17 @@
}
],
"require": {
"php": "^8.0|^8.1|^8.2",
"php": "^8.1|^8.2|^8.3|^8.4",
"ext-mbstring": "*",
"cakephp/chronos": ">=2.0.0",
"illuminate/support": "^8.83.4|^9.3.1|^10.0|^11.0",
"laravel/nova": "^4.0",
"phpunit/phpunit": "^9.0|^10.0|^11.0"
"illuminate/support": "^10.34|^11.0",
"illuminate/testing": "^10.34|^11.0",
"laravel/nova": "^5.0",
"phpunit/phpunit": "^10.0|^11.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
"orchestra/testbench": "^6.0|^8.0|^9.0"
"orchestra/testbench": "^8.0|^9.0"
},
"repositories": [
{
Expand Down
8 changes: 3 additions & 5 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@ name: "novaunit"

services:
php:
build:
context: .docker
dockerfile: php.development.dockerfile
build: .docker
restart: unless-stopped
working_dir: /srv
volumes:
- .:/srv
- ~/.composer:/home/composer/.composer
- ./vendor:/srv/vendor:delegated
- ./storage/xdebug:/tmp/xdebug:delegated
- ./.docker/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini
environment:
XDEBUG_MODE: '${XDEBUG_MODE:-off}'
XDEBUG_CONFIG: '${XDEBUG_CONFIG:-client_host=host.docker.internal}'

extra_hosts:
- "host.docker.internal:host-gateway"

56 changes: 39 additions & 17 deletions src/Actions/MockActionResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

namespace JoshGaber\NovaUnit\Actions;

use Illuminate\Testing\Constraints\ArraySubset;
use JoshGaber\NovaUnit\Constraints\IsActionResponseType;
use Laravel\Nova\Actions\ActionResponse;
use Laravel\Nova\Actions\Responses\Visit;
use PHPUnit\Framework\Assert as PHPUnit;
use PHPUnit\Framework\AssertionFailedError;
use PHPUnit\Framework\Constraint\IsInstanceOf;
use PHPUnit\Framework\Constraint\IsType;

Expand Down Expand Up @@ -43,7 +46,7 @@ public function assertResponseType(string $type, string $message = ''): self
/**
* Asserts the handle response is of type "message".
*
* @param string $message
* @param string $message
* @return $this
*/
public function assertMessage(string $message = ''): self
Expand All @@ -65,7 +68,7 @@ public function assertDanger(string $message = ''): self
/**
* Asserts the handle response is of type "deleted".
*
* @param string $message
* @param string $message
* @return $this
*/
public function assertDeleted(string $message = ''): self
Expand Down Expand Up @@ -98,7 +101,7 @@ public function assertPush(string $message = ''): self
/**
* Asserts the handle response is of type "visit".
*
* @param string|null $path
* @param string $path
* @param array $options
* @return $this
*/
Expand All @@ -108,35 +111,54 @@ public function assertVisit(string $path = '', array $options = []): self
return $this->assertResponseType('visit');
}

return $this->assertResponseContainsArray(['path' => $path, 'options' => array_values($options)], 'visit');
PHPUnit::assertArrayHasKey('visit', $this->response);

$visit = $this->response['visit'];

PHPUnit::logicalAnd(
PHPUnit::assertNotEmpty($visit),
PHPUnit::assertInstanceOf(Visit::class, $visit),
PHPUnit::assertEquals($options, $visit->options),
PHPUnit::assertEquals($path, $visit->path),
);

return $this;
}

/**
* Asserts the handle response is of type "openInNewTab".
*
* @param string $message
* @param string $message
* @return $this
*/
public function assertOpenInNewTab(string $message = ''): self
{
return $this->assertResponseType('openInNewTab', $message);
return $this->assertResponseContainsArray(['openInNewTab' => true], 'redirect', $message);
}

/**
* Asserts the handle response of type "openInNewTab" directs to the specified path.
*/
public function assertOpenInNewTabToPath(string $path, string $message = ''): self
{
return $this->assertResponseContainsArray(['url' => $path, 'openInNewTab' => true], 'redirect', $message);
}

/**
* Asserts the handle response is of type "download".
*
* @param string $message
* @param string $message
* @return $this
*/
public function assertDownload(string $message = ''): self
{
return $this->assertResponseType('download', $message);
}

private function assertResponseContains(string $contents, string $type, string $message = ''): self
private function assertResponseKeyContains(string $contents, string $type, string $key, string $message = ''): self
{
PHPUnit::assertThat(
$this->response[$type] ?? '',
$this->response[$type]?->{$key} ?? '',
PHPUnit::logicalAnd(
PHPUnit::logicalNot(PHPUnit::isEmpty()),
PHPUnit::stringContains($contents, true)
Expand All @@ -150,10 +172,10 @@ private function assertResponseContains(string $contents, string $type, string $
private function assertResponseContainsArray(array $contents, string $type, string $message = ''): self
{
PHPUnit::assertThat(
$this->response[$type] ?? '',
$this->response[$type]?->jsonSerialize() ?? throw new AssertionFailedError(),
PHPUnit::logicalAnd(
PHPUnit::logicalNot(PHPUnit::isEmpty()),
PHPUnit::equalTo($contents)
new ArraySubset($contents, false)
),
$message
);
Expand All @@ -164,25 +186,25 @@ private function assertResponseContainsArray(array $contents, string $type, stri
/**
* Asserts the handle response is a "message" and contains the given text.
*
* @param string $contents The text to assert is in the response
* @param string $message
* @param string $contents The text to assert is in the response
* @param string $message
* @return $this
*/
public function assertMessageContains(string $contents, string $message = ''): self
{
return $this->assertResponseContains($contents, 'message', $message);
return $this->assertResponseKeyContains($contents, 'message', 'text', $message);
}

/**
* Asserts the handle response is a "danger" and contains the given text.
*
* @param string $contents The text to assert is in the response
* @param string $message
* @param string $contents The text to assert is in the response
* @param string $message
* @return $this
*/
public function assertDangerContains(string $contents, string $message = ''): self
{
return $this->assertResponseContains($contents, 'danger', $message);
return $this->assertResponseKeyContains($contents, 'danger', 'text', $message);
}

/**
Expand Down
9 changes: 5 additions & 4 deletions src/Lenses/MockLensRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

namespace JoshGaber\NovaUnit\Lenses;

use Illuminate\Contracts\Database\Eloquent\Builder;
use Laravel\Nova\Http\Requests\LensRequest;

class MockLensRequest extends LensRequest
{
public $withFilters;
public $withOrdering;
public bool $withFilters;
public bool $withOrdering;

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

public function withFilters($query)
public function withFilters(Builder $query): Builder
{
$this->withFilters = true;

return $query;
}

public function withOrdering($query, $defaultCallback = null)
public function withOrdering(Builder $query, $defaultCallback = null): Builder
{
$this->withOrdering = true;

Expand Down
20 changes: 20 additions & 0 deletions tests/Feature/Actions/MockActionResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,26 @@ public function testItSucceedsOnOpenInNewTabResponse()
$mockActionResponse->assertOpenInNewTab();
}

public function testItSucceedsOnOpenInNewTabResponseWithPath()
{
$mockActionResponse = new MockActionResponse(Action::openInNewTab('/test/path'));
$mockActionResponse->assertOpenInNewTabToPath('/test/path');
}

public function testItFailsOnOpenInNewTabResponseWithPathIncorrect()
{
$this->shouldFail();
$mockActionResponse = new MockActionResponse(Action::openInNewTab('/test/path'));
$mockActionResponse->assertOpenInNewTabToPath('/test/wrongpath');
}

public function testItFailsOnOpenInNewTabResponseWithWrongAction()
{
$this->shouldFail();
$mockActionResponse = new MockActionResponse(Action::visit('/test/path'));
$mockActionResponse->assertOpenInNewTabToPath('/test/wrongpath');
}

public function testItFailsOnResponseOtherThanOpenInNewTab()
{
$this->shouldFail();
Expand Down

0 comments on commit 03e24d7

Please sign in to comment.