Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/boost/docs-ported.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ cache.md
collections.md
concurrency.md
configuration.md
console-tests.md
container.md
pagination.md
requests.md
Expand Down
57 changes: 47 additions & 10 deletions src/boost/docs/console-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<a name="introduction"></a>
## Introduction

In addition to simplifying HTTP testing, Laravel provides a simple API for testing your application's [custom console commands](/docs/{{version}}/artisan).
In addition to simplifying HTTP testing, Hypervel provides a simple API for testing your application's [custom console commands](/docs/{{version}}/artisan).

<a name="success-failure-expectations"></a>
## Success / Failure Expectations
Expand All @@ -17,7 +17,7 @@ To get started, let's explore how to make assertions regarding an Artisan comman

```php tab=Pest
test('console command', function () {
$this->artisan('inspire')->assertExitCode(0);
$this->artisan('about')->assertExitCode(0);
});
```

Expand All @@ -27,30 +27,34 @@ test('console command', function () {
*/
public function test_console_command(): void
{
$this->artisan('inspire')->assertExitCode(0);
$this->artisan('about')->assertExitCode(0);
}
```

You may use the `assertNotExitCode` method to assert that the command did not exit with a given exit code:

```php
$this->artisan('inspire')->assertNotExitCode(1);
$this->artisan('about')->assertNotExitCode(1);
```

Of course, all terminal commands typically exit with a status code of `0` when they are successful and a non-zero exit code when they are not successful. Therefore, for convenience, you may utilize the `assertSuccessful` and `assertFailed` assertions to assert that a given command exited with a successful exit code or not:

```php
$this->artisan('inspire')->assertSuccessful();
$this->artisan('about')->assertSuccessful();

$this->artisan('inspire')->assertFailed();
$this->artisan('example:failing-command')->assertFailed();
```

The `assertOk` method is also available as an alias of the `assertSuccessful` method.

<a name="input-output-expectations"></a>
## Input / Output Expectations

Laravel allows you to easily "mock" user input for your console commands using the `expectsQuestion` method. In addition, you may specify the exit code and text that you expect to be output by the console command using the `assertExitCode` and `expectsOutput` methods. For example, consider the following console command:
Hypervel allows you to easily "mock" user input for your console commands using the `expectsQuestion` method. In addition, you may specify the exit code and text that you expect to be output by the console command using the `assertExitCode` and `expectsOutput` methods. For example, consider the following console command:

```php
use Hypervel\Support\Facades\Artisan;

Artisan::command('question', function () {
$name = $this->ask('What is your name?');

Expand All @@ -70,7 +74,11 @@ You may test this command with the following test:
test('console command', function () {
$this->artisan('question')
->expectsQuestion('What is your name?', 'Taylor Otwell')
->expectsQuestion('Which language do you prefer?', 'PHP')
->expectsChoice('Which language do you prefer?', 'PHP', [
'PHP',
'Ruby',
'Python',
])
->expectsOutput('Your name is Taylor Otwell and you prefer PHP.')
->doesntExpectOutput('Your name is Taylor Otwell and you prefer Ruby.')
->assertExitCode(0);
Expand All @@ -85,14 +93,20 @@ public function test_console_command(): void
{
$this->artisan('question')
->expectsQuestion('What is your name?', 'Taylor Otwell')
->expectsQuestion('Which language do you prefer?', 'PHP')
->expectsChoice('Which language do you prefer?', 'PHP', [
'PHP',
'Ruby',
'Python',
])
->expectsOutput('Your name is Taylor Otwell and you prefer PHP.')
->doesntExpectOutput('Your name is Taylor Otwell and you prefer Ruby.')
->assertExitCode(0);
}
```

If you are utilizing the `search` or `multisearch` functions provided by [Laravel Prompts](/docs/{{version}}/prompts), you may use the `expectsSearch` assertion to mock the user's input, search results, and selection:
If the order of the available choices is important, you may pass `true` as the fourth argument to the `expectsChoice` method to assert that the choices are offered in the exact order provided.

If you are utilizing the `search` or `multisearch` functions provided by [Hypervel Prompts](/docs/{{version}}/prompts), you may use the `expectsSearch` assertion to mock the user's input, search results, and selection:

```php tab=Pest
test('console command', function () {
Expand Down Expand Up @@ -193,6 +207,29 @@ $this->artisan('users:all')
]);
```

<a name="prompts-output-expectations"></a>
#### Prompts Output Expectations

If your command displays messages or tables using [Hypervel Prompts](/docs/{{version}}/prompts), you may use the `expectsPromptsInfo`, `expectsPromptsWarning`, `expectsPromptsError`, `expectsPromptsAlert`, `expectsPromptsIntro`, `expectsPromptsOutro`, and `expectsPromptsTable` methods:

```php
$this->artisan('report:generate')
->expectsPromptsInfo('Welcome to the application!')
->expectsPromptsWarning('This action cannot be undone')
->expectsPromptsError('Something went wrong')
->expectsPromptsAlert('Important notice!')
->expectsPromptsIntro('Starting process...')
->expectsPromptsOutro('Process completed!')
->expectsPromptsTable(
headers: ['Name', 'Email'],
rows: [
['Taylor Otwell', 'taylor@example.com'],
['Jason Beggs', 'jason@example.com'],
]
)
->assertExitCode(0);
```

<a name="console-events"></a>
## Console Events

Expand Down
12 changes: 12 additions & 0 deletions src/jwt/src/Blacklist.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ protected function getGraceTimestamp(): int
/**
* Set the grace period.
*
* Only call this once at boot (service provider). Blacklist is a
* worker-lifetime singleton; runtime mutation affects every subsequent
* request and races across coroutines.
*
* @return $this
*/
public function setGracePeriod(int $gracePeriod): static
Expand Down Expand Up @@ -152,6 +156,10 @@ public function getKey(array $payload): mixed
/**
* Set the unique key held within the blacklist.
*
* Only call this once at boot (service provider). Blacklist is a
* worker-lifetime singleton; runtime mutation affects every subsequent
* request and races across coroutines.
*
* @return $this
*/
public function setKey(string $key): static
Expand All @@ -164,6 +172,10 @@ public function setKey(string $key): static
/**
* Set the refresh time limit.
*
* Only call this once at boot (service provider). Blacklist is a
* worker-lifetime singleton; runtime mutation affects every subsequent
* request and races across coroutines.
*
* @return $this
*/
public function setRefreshTTL(int $ttl): static
Expand Down
13 changes: 13 additions & 0 deletions src/jwt/src/Providers/Lcobucci.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,19 @@ protected function buildConfig(): Configuration
return $config;
}

/**
* Rebuild cached derived state after a configuration change.
*
* Signer is rebuilt before config because buildConfig() reads $this->signer.
*
* @throws \Hypervel\JWT\Exceptions\JWTException
*/
protected function onConfigurationChanged(): void
{
$this->signer = $this->getSigner();
$this->config = $this->buildConfig();
}

/**
* Get the signer instance.
*
Expand Down
25 changes: 25 additions & 0 deletions src/jwt/src/Providers/Provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,16 @@ public function __construct(
/**
* Set the algorithm used to sign the token.
*
* Only call this once at boot (service provider). Providers are cached
* on the singleton JWTManager; runtime mutation affects every subsequent
* request and races across coroutines.
*
* @return $this
*/
public function setAlgo(string $algo): static
{
$this->algo = $algo;
$this->onConfigurationChanged();

return $this;
}
Expand All @@ -59,11 +64,16 @@ public function getAlgo(): string
/**
* Set the secret used to sign the token.
*
* Only call this once at boot (service provider). Providers are cached
* on the singleton JWTManager; runtime mutation affects every subsequent
* request and races across coroutines.
*
* @return $this
*/
public function setSecret(string $secret): static
{
$this->secret = $secret;
$this->onConfigurationChanged();

return $this;
}
Expand All @@ -79,11 +89,16 @@ public function getSecret(): string
/**
* Set the keys used to sign the token.
*
* Only call this once at boot (service provider). Providers are cached
* on the singleton JWTManager; runtime mutation affects every subsequent
* request and races across coroutines.
*
* @return $this
*/
public function setKeys(array $keys): static
{
$this->keys = $keys;
$this->onConfigurationChanged();

return $this;
}
Expand Down Expand Up @@ -141,4 +156,14 @@ protected function getVerificationKey(): mixed
* Determine if the algorithm is asymmetric, and thus requires a public/private key combo.
*/
abstract protected function isAsymmetric(): bool;

/**
* Hook fired after any of algo/secret/keys is mutated.
*
* Subclasses that cache derived state (signers, configuration objects)
* override this to rebuild it so the new values actually take effect.
*/
protected function onConfigurationChanged(): void
{
}
}
28 changes: 28 additions & 0 deletions tests/Integration/Routing/MethodOverrideTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Hypervel\Tests\Integration\Routing;

use Hypervel\Support\Facades\Route;

class MethodOverrideTest extends RoutingTestCase
{
public function testPostBodyMethodOverrideDispatchesToPutRoute()
{
Route::put('/widgets/{widget}', fn (string $widget) => "updated-{$widget}");

$this->post('/widgets/42', ['_method' => 'PUT'])
->assertOk()
->assertContent('updated-42');
}

public function testQueryStringMethodOverrideDispatchesToPutRoute()
{
Route::put('/widgets/{widget}', fn (string $widget) => "updated-{$widget}");

$this->post('/widgets/42?_method=PUT')
->assertOk()
->assertContent('updated-42');
}
}
File renamed without changes.
File renamed without changes.
28 changes: 28 additions & 0 deletions tests/JWT/Fixtures/keys/id_rsa_alt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDLJsCnfubmsSOx
JkG1m4kgMdKjtEUdpwukZr6ejWWP5dTnZJgOI+O0wWMgspNHPzhlQpBk4xg0fWnf
oMsU4eFG178Lj1135AIPt3tBuVudZREmxTpC5H65A+J6L6iU9wNQVDW1JM+p8qQg
v3nWi8kOOSk9xgp6nLfD6qZO83lro5wKTLhmAPpHivfwDg5B4v9DVDjXeW0cnrHN
dcfYQi7e4DlQ5n3nyxOh7BXnc0Xk95EskWuzkuuoTqnhDE9ixYJB+6R2UhoAXfSs
JxgQwmVLSSExqEfu/a1C4Jc0cFtIxNchVpnXsAIQb9rQUjNdkPJ9Dl9NnGDke/B8
QN1rOpfrAgMBAAECggEAObUV596AB8sM6P8FjmmSv873V2JXec9gWsCG6HIhBgnS
+zITkXy3a7q9hmXDuWrngbgxXT83On3fq9M4rQNnI2EY11dPxUVDIqTLwgU91Y2G
nD1NSgAvUS4d0Pilyj8KtXBeW0kMJmoTHmxV11CY+c3Z/b66bk8DUode27GE7cKn
0plc+56arqYwEr2LqDLy2Sr7GiB57FDSHlB0gd2aDH7oPjg2KFsq1OOIGIWvVZf9
g3g53usStoA0PK/iAnRnxbrYsF1fxFOO65EIW5A9Xu+X7UygJr4LtalBdYUsuW+H
5+156BN9qr57LNy9upz+QVexFihM1mM8vjOmmUkZxQKBgQDvfBKGQ6f+NiP5/1Mb
4S9VqgWLbtRR7j5n87L8sjJicWa6lqXU0pnoO2S2BAqo48uF+TEuPc3XsTKAo5e6
ByBddNVHRRc4dk19MmomZESuSgZPVGl2lVDxlUEWiqUxm1JZD4NWl4BRBu1fUVVC
eC080TJvu0fzvb03+65sYtSe1wKBgQDZKT4WGHrZjIMYsABkWDyI6tyGTHs4HduH
LCTChbF3WOyI3gpyqUucT6mRNpmMj6atBNvrww12dSClyVvgahzRVFfzvrAroNT3
86E1dY92NOd/6kmniNpAGY6ZxOxHgKDgqOQhgSRGUUE4WdOTdVdgaLSmRc5BbTub
kgmekifRDQKBgQCpO5w7lQPZ+JhjybIJOZAhkQxqA9+2Jg2jl+sb9zDzr/9QS7TU
OB7apV394c1Gm/LusbG3Y6VajrWJghFuPCr639z3iDNoivEnT8EDcEe4gkcDODtu
uQWCMl7UdxVVgNUoanX9cwISQDrt6KO/XP1axNpHaqjl7WcRcKFJpm1p8QKBgQCf
gUyKHDb33d5Y3sWa7rif9Ko/tqN2529cjM7/VgWw3M74BOd1quXPjS/Gam1EMitB
wGTseZtE2+k7/HeQkUBTfPkRHon1sa9b5EYPpybVsywq52JsPPfZxyvXxC2so00H
VuYhueJ0B7C4/DmMgM7KEH5H9tP1eI8kyJJqN34pbQKBgAi+QUUkTzjGsmGJcx/s
7ulPWIZLpUlcwB8P4y7+crPJ4JprNuc+LVdAKi0H/JOGpUgkwcvsRMhNmtstZeQ9
B0lP5Oxs4hr1CjQ7Gz5v4fFvl1T33Oa0ThyqrlZ9eT8i3TFToXU3xXA/qeqglZff
986zyaNhxIG04t1SxmHNX7YM
-----END PRIVATE KEY-----
9 changes: 9 additions & 0 deletions tests/JWT/Fixtures/keys/id_rsa_alt.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyybAp37m5rEjsSZBtZuJ
IDHSo7RFHacLpGa+no1lj+XU52SYDiPjtMFjILKTRz84ZUKQZOMYNH1p36DLFOHh
Rte/C49dd+QCD7d7QblbnWURJsU6QuR+uQPiei+olPcDUFQ1tSTPqfKkIL951ovJ
DjkpPcYKepy3w+qmTvN5a6OcCky4ZgD6R4r38A4OQeL/Q1Q413ltHJ6xzXXH2EIu
3uA5UOZ958sToewV53NF5PeRLJFrs5LrqE6p4QxPYsWCQfukdlIaAF30rCcYEMJl
S0khMahH7v2tQuCXNHBbSMTXIVaZ17ACEG/a0FIzXZDyfQ5fTZxg5HvwfEDdazqX
6wIDAQAB
-----END PUBLIC KEY-----
Loading