chore: coding style changes

This commit is contained in:
nuno maduro
2026-08-07 14:52:56 +01:00
parent eb88513baf
commit 42d9b777bf
221 changed files with 139 additions and 3086 deletions
@@ -1,5 +1,5 @@
Pest Testing Framework 5.0.4.
Pest Testing Framework 5.0.5.
USAGE: pest <file> [options]
@@ -1,3 +1,3 @@
Pest Testing Framework 5.0.4.
Pest Testing Framework 5.0.5.
+7 -4
View File
@@ -73,9 +73,9 @@
↓ is marked as todo 3
↓ shouldBeMarkedAsTodo
WARN Tests\Features\Coverage
PASS Tests\Features\Coverage
✓ it has plugin
- it adds coverage if --coverage exist → Coverage is not available
it adds coverage if --coverage exist
✓ it adds coverage if --min exist
✓ it generates coverage based on file input
@@ -1709,7 +1709,7 @@
PASS Tests\Features\Tia\LivewireComponents
✓ a changed single-file component selects only the tests that rendered it, across workers
✓ a changed multi-file component class selects the tests that rendered the component
✓ a changed multi-file component asset selects the tests that rendered the component
✓ a deleted single-file component selects the tests that rendered it
✓ a Blade file with no generated view still falls back to the watch pattern
@@ -2119,6 +2119,9 @@
✓ Livewire component views → it maps documented MFC locations using the component directory hash with dataset "default component location"
✓ Livewire component views → it maps documented MFC locations using the component directory hash with dataset "default component location without emoji"
✓ Livewire component views → it maps documented MFC locations using the component directory hash with dataset "index convention"
✓ Livewire component views → it maps a changed MFC sibling through the component directory hash with dataset "class sibling via the generated class"
✓ Livewire component views → it maps a changed MFC sibling through the component directory hash with dataset "class sibling via the generated view"
✓ Livewire component views → it maps a changed MFC sibling through the component directory hash with dataset "asset sibling via the generated view"
✓ Livewire component views → it preserves direct view edges for class-based components
✓ Livewire component views → it falls back to watch patterns when no generated view matches
✓ markKnownTestFiles() → it makes a test file with no edges known
@@ -2432,4 +2435,4 @@
✓ pass with dataset with ('my-datas-set-value')
✓ within describe → pass with dataset with ('my-datas-set-value')
Tests: 1 deprecated, 4 warnings, 5 incomplete, 2 notices, 40 todos, 35 skipped, 1756 passed (3974 assertions)
Tests: 1 deprecated, 4 warnings, 5 incomplete, 2 notices, 40 todos, 34 skipped, 1760 passed (3983 assertions)
+1 -1
View File
@@ -16,6 +16,6 @@ test('deletes file after all', function () use ($file): void {
file_put_contents($file, 'foo');
expect($file)->toBeFile();
register_shutdown_function(function (): void {
// $this->assertFileDoesNotExist($file);
//
});
});
@@ -5,13 +5,13 @@ declare(strict_types=1);
beforeEach()->expect(true)->toBeTrue();
test('runs 1', function (): void {
// This test did performs assertions...
//
});
test('runs 2', function (): void {
// This test did performs assertions...
//
});
test('runs 3', function (): void {
// This test did performs assertions...
//
});
-47
View File
@@ -1,16 +1,5 @@
<?php
/**
* Tests for dataset method chaining with hooks and describe blocks.
*
* Covers the fix from PR #1565: beforeEach()->with(), describe()->with(),
* and nested describe blocks with datasets.
*/
// ---------------------------------------------------------------
// beforeEach()->with() inside describe blocks
// ---------------------------------------------------------------
describe('beforeEach()->with() applies dataset to tests', function (): void {
beforeEach()->with([10]);
@@ -50,10 +39,6 @@ describe('beforeEach()->with() with closure dataset', function (): void {
});
});
// ---------------------------------------------------------------
// describe()->with() method chaining
// ---------------------------------------------------------------
describe('describe()->with() passes dataset to tests', function (): void {
test('receives the dataset value', function ($value): void {
expect($value)->toBe(42);
@@ -85,10 +70,6 @@ describe('describe()->with() with closure dataset', function (): void {
yield [14];
});
// ---------------------------------------------------------------
// Nested describe blocks with datasets
// ---------------------------------------------------------------
describe('outer with dataset', function (): void {
describe('inner without dataset', function (): void {
test('inherits outer dataset', function (...$args): void {
@@ -123,10 +104,6 @@ describe('deeply nested describe with datasets', function (): void {
})->with([1]);
});
// ---------------------------------------------------------------
// Combining hook datasets with test-level datasets
// ---------------------------------------------------------------
describe('beforeEach()->with() combined with test->with()', function (): void {
beforeEach()->with([10]);
@@ -143,10 +120,6 @@ describe('describe()->with() combined with test->with()', function (): void {
})->with([50, 60]);
})->with([5]);
// ---------------------------------------------------------------
// beforeEach()->with() combined with beforeEach closure
// ---------------------------------------------------------------
describe('beforeEach closure and beforeEach()->with() coexist', function (): void {
beforeEach(function (): void {
$this->setupValue = 'initialized';
@@ -177,10 +150,6 @@ describe('beforeEach()->with() does not interfere with closure hooks', function
});
});
// ---------------------------------------------------------------
// Dataset isolation between describe blocks
// ---------------------------------------------------------------
describe('first describe with dataset', function (): void {
beforeEach()->with([111]);
@@ -203,10 +172,6 @@ describe('third describe without dataset', function (): void {
});
});
// ---------------------------------------------------------------
// describe()->with() combined with beforeEach hooks
// ---------------------------------------------------------------
describe('describe()->with() with beforeEach closure', function (): void {
beforeEach(function (): void {
$this->hookRan = true;
@@ -229,10 +194,6 @@ describe('describe()->with() with afterEach closure', function (): void {
});
})->with([88]);
// ---------------------------------------------------------------
// Multiple tests in a describe with beforeEach()->with()
// ---------------------------------------------------------------
describe('multiple tests share the same beforeEach dataset', function (): void {
beforeEach()->with([33]);
@@ -249,10 +210,6 @@ describe('multiple tests share the same beforeEach dataset', function (): void {
});
});
// ---------------------------------------------------------------
// Nested describe with beforeEach()->with() at inner level
// ---------------------------------------------------------------
describe('outer describe', function (): void {
beforeEach(function (): void {
$this->outer = true;
@@ -272,10 +229,6 @@ describe('outer describe', function (): void {
});
});
// ---------------------------------------------------------------
// describe()->with() with depends
// ---------------------------------------------------------------
describe('describe()->with() preserves depends', function (): void {
test('first', function ($value): void {
expect($value)->toBe(9);
+2 -3
View File
@@ -38,7 +38,6 @@ it('gets bound to test case object', function ($value): void {
test('it truncates the description', function (): void {
expect(true)->toBeTrue();
// it gets tested by the integration test
})->with([str_repeat('Fooo', 10)]);
$state = new stdClass;
@@ -294,7 +293,7 @@ it('resolves a potential bound dataset logically', function ($foo, $bar): void {
[
'foo',
fn (): string => 'bar',
], // This should be passed as a closure because we've passed multiple arguments
],
]);
it('resolves a potential bound dataset logically even when the closure comes first', function ($foo, $bar): void {
@@ -303,7 +302,7 @@ it('resolves a potential bound dataset logically even when the closure comes fir
})->with([
[
fn (): string => 'foo', 'bar',
], // This should be passed as a closure because we've passed multiple arguments
],
]);
it('will not resolve a closure if it is type hinted as a closure', function (Closure $data): void {
-1
View File
@@ -33,7 +33,6 @@ test('depends run test only once', function () use (&$runCounter): void {
expect($runCounter)->toBe(2);
})->depends('first', 'second');
// Regression tests. See https://github.com/pestphp/pest/pull/216
it('asserts true is true')->assertTrue(true);
test('depends works with the correct test name')->assertTrue(true)->depends('it asserts true is true');
+2 -2
View File
@@ -26,12 +26,12 @@ trait Gettable
}
}
get('foo'); // not incomplete because closure is created...
get('foo');
get('foo')->get('bar')->expect(true)->toBeTrue();
get('foo')->expect(true)->toBeTrue();
describe('a "describe" group of tests', function (): void {
get('foo'); // not incomplete because closure is created...
get('foo');
get('foo')->get('bar')->expect(true)->toBeTrue();
get('foo')->expect(true)->toBeTrue();
});
+11 -22
View File
@@ -10,13 +10,9 @@ it('expects on each item', function (): void {
expect([1, 1, 1])
->each()
->toEqual(1)
->and(static::getCount())->toBe(3); // + 1 assertion
expect([1, 1, 1])
->each
->toEqual(1);
expect(static::getCount())->toBe(7);
->and(static::getCount())->toBe(3)
->and([1, 1, 1])->each->toEqual(1)
->and(static::getCount())->toBe(7);
});
it('chains expectations on each item', function (): void {
@@ -24,14 +20,8 @@ it('chains expectations on each item', function (): void {
->each()
->toBeInt()
->toEqual(1)
->and(static::getCount())->toBe(6); // + 1 assertion
expect([2, 2, 2])
->each
->toBeInt
->toEqual(2);
expect(static::getCount())->toBe(13);
->and(static::getCount())->toBe(6)->and([2, 2, 2])->each->toBeInt->toEqual(2)
->and(static::getCount())->toBe(13);
});
test('opposite expectations on each item', function (): void {
@@ -60,18 +50,17 @@ test('chained opposite and non-opposite expectations', function (): void {
it('can add expectations via "and"', function (): void {
expect([1, 2, 3])
->each()
->toBeInt // + 3
->toBeInt
->and([4, 5, 6])
->each
->toBeLessThan(7) // + 3
->toBeLessThan(7)
->not
->toBeLessThan(3)
->toBeGreaterThan(3) // + 3
->toBeGreaterThan(3)
->and('Hello World')
->toBeString // + 1
->toEqual('Hello World'); // + 1
expect(static::getCount())->toBe(14);
->toBeString
->toEqual('Hello World')
->and(static::getCount())->toBe(14);
});
it('accepts callables', function (): void {
+3 -20
View File
@@ -12,7 +12,7 @@ class Number
public function __construct(
public int $value
) {
// ..
//
}
}
@@ -21,7 +21,7 @@ class Char
public function __construct(
public string $value
) {
// ..
//
}
}
@@ -30,7 +30,7 @@ class Symbol
public function __construct(
public string $value
) {
// ..
//
}
}
@@ -58,9 +58,6 @@ class State
$state = new State;
/*
* Overrides toBe to assert two Characters are the same
*/
expect()->pipe('toBe', function ($next, $expected) use ($state): void {
$state->runCount['char']++;
@@ -70,17 +67,12 @@ expect()->pipe('toBe', function ($next, $expected) use ($state): void {
assertInstanceOf(Char::class, $expected);
assertEquals($this->value->value, $expected->value);
// returning nothing stops pipeline execution
return;
}
// calling $next(); let the pipeline to keep running
$next();
});
/*
* Overrides toBe to assert two Number objects are the same
*/
expect()->intercept('toBe', Number::class, function ($expected) use ($state): void {
$state->runCount['number']++;
$state->appliedCount['number']++;
@@ -89,17 +81,11 @@ expect()->intercept('toBe', Number::class, function ($expected) use ($state): vo
assertEquals($this->value->value, $expected->value);
});
/*
* Overrides toBe to assert all integers are allowed if value is a wildcard (*)
*/
expect()->intercept('toBe', fn ($value, $expected) => $value === '*' && is_numeric($expected), function ($expected) use ($state): void {
$state->runCount['wildcard']++;
$state->appliedCount['wildcard']++;
});
/*
* Overrides toBe to assert to Symbols are the same
*/
expect()->pipe('toBe', function ($next, $expected) use ($state): void {
$state->runCount['symbol']++;
@@ -114,9 +100,6 @@ expect()->pipe('toBe', function ($next, $expected) use ($state): void {
$next();
});
/*
* Overrides toBe to allow ignoring case when checking strings
*/
expect()->intercept('toBe', fn ($value) => is_string($value), function ($expected, $ignoreCase = false): void {
if ($ignoreCase) {
assertEqualsIgnoringCase($expected, $this->value);
+5 -5
View File
@@ -6,11 +6,11 @@ use Pest\Exceptions\InvalidExpectationValue;
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function (): void {
expect('Zm9v')->toBeBase64() // 'foo' (no padding)
->and('Zm9vYg==')->toBeBase64() // 'foob' (with padding)
->and('Zm9vYmE=')->toBeBase64() // 'fooba' (with padding)
->and('Zm9vYmFy')->toBeBase64() // 'foobar' (no padding)
->and('')->toBeBase64(); // empty string
expect('Zm9v')->toBeBase64()
->and('Zm9vYg==')->toBeBase64()
->and('Zm9vYmE=')->toBeBase64()
->and('Zm9vYmFy')->toBeBase64()
->and('')->toBeBase64();
});
test('failures', function (): void {
+4 -4
View File
@@ -6,10 +6,10 @@ use Pest\Exceptions\InvalidExpectationValue;
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function (): void {
expect('example.com')->toBeDomain() // standard domain
->and('sub.example.com')->toBeDomain() // subdomain
->and('my-host.io')->toBeDomain() // with hyphen
->and('example.co.uk')->toBeDomain(); // multi-level TLD
expect('example.com')->toBeDomain()
->and('sub.example.com')->toBeDomain()
->and('my-host.io')->toBeDomain()
->and('example.co.uk')->toBeDomain();
});
test('failures', function (): void {
+5 -5
View File
@@ -6,11 +6,11 @@ use Pest\Exceptions\InvalidExpectationValue;
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function (): void {
expect('abcdef')->toBeHexadecimal() // lowercase
->and('ABCDEF')->toBeHexadecimal() // uppercase
->and('aBcDeF')->toBeHexadecimal() // mixed case
->and('1234567890')->toBeHexadecimal() // numeric
->and('deadbeef')->toBeHexadecimal(); // alphanumeric
expect('abcdef')->toBeHexadecimal()
->and('ABCDEF')->toBeHexadecimal()
->and('aBcDeF')->toBeHexadecimal()
->and('1234567890')->toBeHexadecimal()
->and('deadbeef')->toBeHexadecimal();
});
test('failures', function (): void {
+4 -4
View File
@@ -6,10 +6,10 @@ use Pest\Exceptions\InvalidExpectationValue;
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function (): void {
expect('example')->toBeHostname() // single label
->and('example.com')->toBeHostname() // multiple labels
->and('sub.example.com')->toBeHostname() // subdomain
->and('my-host')->toBeHostname(); // with hyphen
expect('example')->toBeHostname()
->and('example.com')->toBeHostname()
->and('sub.example.com')->toBeHostname()
->and('my-host')->toBeHostname();
});
test('failures', function (): void {
+2 -2
View File
@@ -6,8 +6,8 @@ use Pest\Exceptions\InvalidExpectationValue;
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function (): void {
expect('00:1a:2b:3c:4d:5e')->toBeMacAddress() // colon-separated
->and('00-1a-2b-3c-4d-5e')->toBeMacAddress() // hyphen-separated
expect('00:1a:2b:3c:4d:5e')->toBeMacAddress()
->and('00-1a-2b-3c-4d-5e')->toBeMacAddress()
->and('ff:ff:ff:ff:ff:ff')->toBeMacAddress();
});
+8 -8
View File
@@ -10,14 +10,14 @@ test('failures with wrong type', function (): void {
})->throws(InvalidExpectationValue::class, 'Invalid expectation value type. Expected [string].');
test('pass', function (): void {
expect('3cafb226-4326-11ee-a516-846993788c86')->toBeUuid(); // version 1
expect('0000415c-4326-21ee-a700-846993788c86')->toBeUuid(); // version 2
expect('3f703955-aaba-3e70-a3cb-baff6aa3b28f')->toBeUuid(); // version 3
expect('ca0a8228-cdf6-41db-b34b-c2f31485796c')->toBeUuid(); // version 4
expect('a35477ae-bfb1-5f2e-b5a4-4711594d855f')->toBeUuid(); // version 5
expect('1ee43263-cf5a-6fd8-8f47-846993788c86')->toBeUuid(); // version 6
expect('018a2bef-09f2-728c-becb-c3f569d91486')->toBeUuid(); // version 7
expect('00112233-4455-8677-8899-aabbccddeeff')->toBeUuid(); // version 8
expect('3cafb226-4326-11ee-a516-846993788c86')->toBeUuid()
->and('0000415c-4326-21ee-a700-846993788c86')->toBeUuid()
->and('3f703955-aaba-3e70-a3cb-baff6aa3b28f')->toBeUuid()
->and('ca0a8228-cdf6-41db-b34b-c2f31485796c')->toBeUuid()
->and('a35477ae-bfb1-5f2e-b5a4-4711594d855f')->toBeUuid()
->and('1ee43263-cf5a-6fd8-8f47-846993788c86')->toBeUuid()
->and('018a2bef-09f2-728c-becb-c3f569d91486')->toBeUuid()
->and('00112233-4455-8677-8899-aabbccddeeff')->toBeUuid();
});
test('failures', function (): void {
@@ -1,5 +1,3 @@
<?php
declare(strict_types=1);
// ...
@@ -2,12 +2,10 @@
use Pest\Arch\Exceptions\ArchExpectationFailedException;
use Pest\Configuration;
use Pest\Expectation;
use Tests\Fixtures\Inheritance\ExampleTest;
it('passes', function (): void {
expect(Expectation::class)->toHaveMethodsDocumented()
->and(ExampleTest::class)->not->toHaveMethodsDocumented();
expect(ExampleTest::class)->not->toHaveMethodsDocumented();
});
it('fails 1', function (): void {
+3 -9
View File
@@ -41,15 +41,11 @@ it('skips with falsy', function (): void {
expect($this->unlessObject)
->unless(
1,
function ($value) {
return $value->trueValue->toBeFalse(); // fails
}
fn ($value) => $value->trueValue->toBeFalse()
)
->unless(
true,
function ($value) {
return $value->trueValue->toBeFalse(); // fails
}
fn ($value) => $value->trueValue->toBeFalse()
)
->foo->toEqual('foo')
->and(static::getCount())->toBe(1);
@@ -69,9 +65,7 @@ it('skips with falsy closure condition', function (): void {
expect($this->unlessObject)
->unless(
fn (): string => '1',
function ($value) {
return $value->trueValue->toBeFalse(); // fails
}
fn ($value) => $value->trueValue->toBeFalse()
)
->foo->toEqual('foo')
->and(static::getCount())->toBe(1);
+3 -9
View File
@@ -41,15 +41,11 @@ it('skips with falsy', function (): void {
expect($this->whenObject)
->when(
0,
function ($value) {
return $value->trueValue->toBeFalse(); // fails
}
fn ($value) => $value->trueValue->toBeFalse()
)
->when(
false,
function ($value) {
return $value->trueValue->toBeFalse(); // fails
}
fn ($value) => $value->trueValue->toBeFalse()
)
->foo->toEqual('foo')
->and(static::getCount())->toBe(1);
@@ -69,9 +65,7 @@ it('skips with falsy closure condition', function (): void {
expect($this->whenObject)
->when(
fn (): string => '0',
function ($value) {
return $value->trueValue->toBeFalse(); // fails
}
fn ($value) => $value->trueValue->toBeFalse()
)
->foo->toEqual('foo')
->and(static::getCount())->toBe(1);
+1 -11
View File
@@ -100,7 +100,6 @@ describe('lifecycle hooks with flaky', function (): void {
}
@unlink($file);
// After retry: setUp ran for initial + retry = setupCount should be 2
expect($this->setupCount)->toBe(2);
})->flaky(tries: 3);
});
@@ -123,7 +122,6 @@ describe('afterEach with flaky', function (): void {
}
@unlink($file);
// tearDown was called once between retries
expect($state->teardownCount)->toBe(1);
})->flaky(tries: 3);
});
@@ -184,9 +182,6 @@ it('works with throws and flaky', function (): void {
})->throws(RuntimeException::class, 'Expected exception')->flaky(tries: 2);
it('does not retry expected exceptions', function (): void {
// If flaky retried this, the temp file counter would reach 2 and
// the test would NOT throw — causing PHPUnit's "expected exception
// was not raised" to fail. The test passes only if we don't retry.
$file = sys_get_temp_dir().'/pest_flaky_expected';
$count = file_exists($file) ? (int) file_get_contents($file) : 0;
file_put_contents($file, (string) ++$count);
@@ -194,8 +189,6 @@ it('does not retry expected exceptions', function (): void {
if ($count >= 2) {
@unlink($file);
// Second call means flaky retried — don't throw, which will FAIL
// because PHPUnit expects the exception
return;
}
@@ -229,18 +222,16 @@ it('does not leak mock objects between retries', function (): void {
file_put_contents($file, (string) ++$count);
if ($count < 2) {
@unlink(sys_get_temp_dir().'/pest_flaky_mock'); // clean before retry writes again
@unlink(sys_get_temp_dir().'/pest_flaky_mock');
file_put_contents($file, '1');
throw new Exception('Flaky mock failure');
}
@unlink($file);
// Call mock — only the mock from THIS attempt should be verified
expect($mock->count())->toBe(1);
})->flaky(tries: 3);
it('does not stop retrying when snapshot changes are absent', function (): void {
// Ensures the snapshot guard only triggers when __snapshotChanges is non-empty
$file = sys_get_temp_dir().'/pest_flaky_no_snapshot';
$count = file_exists($file) ? (int) file_get_contents($file) : 0;
file_put_contents($file, (string) ++$count);
@@ -294,6 +285,5 @@ it('preserves output between retries when no output expectation is set', functio
}
@unlink($file);
// Output from attempt 1 is still in the buffer
$this->expectOutputString('from attempt 1');
})->flaky(tries: 3);
-2
View File
@@ -26,7 +26,6 @@ it('does not run user hooks when replaying cached skipped and incomplete results
$graph = new Graph($projectRoot);
$graph->setFingerprint(Fingerprint::compute($projectRoot));
$graph->setRecordedAtSha($branch, $sha);
// Hashes the working tree as it stands, so the replay sees nothing as changed.
$graph->setLastRunTree($branch, $changedFiles->snapshotTree($changedFiles->since($sha) ?? []));
$graph->markKnownTestFiles([$fixture]);
$graph->setResult($branch, $id('replayed pass'), 0, '', 0.01, 1, $fixture);
@@ -64,7 +63,6 @@ it('does not run user hooks when replaying cached skipped and incomplete results
$output = removeAnsiEscapeSequences($process->getOutput().$process->getErrorOutput());
// Both hooks throw, so the run stays green only if neither one ran.
expect($output)->toContain('3 replayed')
->and($output)->not->toContain('must not run for replayed tests')
->and($output)->toContain('1 incomplete, 1 skipped, 1 passed')
+3 -12
View File
@@ -8,12 +8,6 @@ afterEach(function (): void {
Project::destroyAll();
});
/**
* Livewire never renders a single- or multi-file component source directly: it
* compiles it into `<compiled views>/livewire/{views,classes}/<hash>.<ext>` and
* renders that, so the recorded graph only ever holds the generated path. These
* helpers seed the graph the way a real recording run would leave it.
*/
function tiaLivewireHash(string $sourcePath): string
{
return substr(md5(DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $sourcePath)), 0, 8);
@@ -44,7 +38,6 @@ test('a changed single-file component selects only the tests that rendered it, a
$hash = tiaLivewireHash('resources/views/pages/⚡orders.blade.php');
// The same component, compiled once per parallel worker.
tiaSeedWithGeneratedViews($project, [
'storage/framework/views/test_1/livewire/views/'.$hash.'.blade.php' => 'tests/Unit/GreeterTest.php',
'storage/framework/views/test_2/livewire/views/'.$hash.'.blade.php' => 'tests/Unit/CalculatorTest.php',
@@ -60,20 +53,18 @@ test('a changed single-file component selects only the tests that rendered it, a
->and($result->replayed())->toBe(2, $result->describe());
})->skipOnWindows();
test('a changed multi-file component class selects the tests that rendered the component', function (): void {
test('a changed multi-file component asset selects the tests that rendered the component', function (): void {
$project = Project::make('master', 'livewire-watch');
$project->write('resources/views/components/⚡counter/counter.blade.php', "<div>{{ \$count }}</div>\n");
$project->write('resources/views/components/⚡counter/counter.php', "<?php\n\nreturn 1;\n");
$project->write('resources/views/components/⚡counter/counter.js', "export default 1\n");
$project->git()->commit('add the component');
// A multi-file component is compiled under the hash of its *directory*, and
// its class is what PHP executes — so the class sibling, not the view, is
// what the graph can be reached through.
tiaSeedWithGeneratedViews($project, [
'storage/framework/views/livewire/classes/'.tiaLivewireHash('resources/views/components/⚡counter').'.php' => 'tests/Unit/GreeterTest.php',
]);
$project->write('resources/views/components/⚡counter/counter.php', "<?php\n\nreturn 2;\n");
$project->write('resources/views/components/⚡counter/counter.js', "export default 2\n");
$project->snapshot();
$result = $project->pest('--tia');
@@ -2,8 +2,6 @@
/** @noinspection PhpUnused */
// some other comment
declare(strict_types=1);
namespace Tests\Fixtures\Arch\ToUseStrictTypes;
@@ -5,8 +5,4 @@ declare(strict_types=1);
require_once __DIR__.'/../app/Calculator.php';
require_once __DIR__.'/../app/Greeter.php';
// Stands in for the built-in Laravel/Livewire watch defaults, which are not
// applicable here because the fixture installs neither package. Without the
// generated-view mapping, every changed Blade file lands on this rule and
// invalidates the whole suite — which is exactly what issue #1808 reported.
pest()->tia()->watch(['resources/views/**' => 'tests']);
@@ -1,10 +1,3 @@
<?php
/*
* NOTE: To preserve cross-platform testing compatibility we cannot use ! * and
* other Windows reserved characters in this test's filename.
*
* See https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions
*/
it(sprintf('runs file names like `%s`', basename(__FILE__)))->assertTrue(true);
@@ -20,5 +20,3 @@ class ExecutedTest extends TestCase
assertTrue(true);
}
}
// register_shutdown_function(fn () => assertTrue(ExecutedTest::$executed));
+2 -5
View File
@@ -11,17 +11,14 @@ pest()->project()->github('pestphp/pest');
pest()->in('PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder')->use(CustomTestCaseInSubFolder::class);
// test case for all the directories inside PHPUnit/GlobPatternTests/SubFolder/
pest()->in('PHPUnit/GlobPatternTests/SubFolder/*')->extend(CustomTestCase::class);
// test case for all the files that end with AsPattern.php inside PHPUnit/GlobPatternTests/SubFolder2/
pest()->in('PHPUnit/GlobPatternTests/SubFolder2/*AsPattern.php')->use(CustomTestCase::class);
pest()->in('Visual')->group('integration');
pest()->in('Features/Tia')->group('integration', 'tia');
// NOTE: global test value container to be mutated and checked across files, as needed
$_SERVER['globalHook'] = (object) ['calls' => (object) ['beforeAll' => 0, 'afterAll' => 0]];
pest()
@@ -90,8 +87,8 @@ function removeAnsiEscapeSequences(string $input): ?string
{
return preg_replace(
[
'#\\x1b[[][^A-Za-z]*[A-Za-z]#', // CSI (colors, cursor, etc.)
'#\\x1b\\]8;[^\\x1b\\x07]*(?:\\x1b\\\\|\\x07)#', // OSC 8 hyperlinks
'#\\x1b[[][^A-Za-z]*[A-Za-z]#',
'#\\x1b\\]8;[^\\x1b\\x07]*(?:\\x1b\\\\|\\x07)#',
],
'',
$input,
-1
View File
@@ -34,7 +34,6 @@ describe('keysWithPrefix()', function (): void {
$state = new FileState($this->root);
$state->write('worker-edges-a.json', '{}');
// Simulate another process mid-write: its temp file exists but has not been renamed yet.
file_put_contents($this->root.'/worker-edges-b.json.'.bin2hex(random_bytes(4)).'.tmp', '{');
expect($state->keysWithPrefix('worker-edges-'))->toBe(['worker-edges-a.json']);
+20 -1
View File
@@ -232,6 +232,26 @@ describe('Livewire component views', function (): void {
'index convention' => ['resources/views/components/post/⚡index', 'resources/views/components/post/⚡index/index.blade.php'],
]);
it('maps a changed MFC sibling through the component directory hash', function (string $sibling, string $generated): void {
$componentDirectory = 'resources/views/components/post/⚡create';
$hash = substr(md5(DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $componentDirectory)), 0, 8);
mkdir($this->projectRoot.'/'.$componentDirectory, 0755, true);
file_put_contents($this->projectRoot.'/'.$componentDirectory.'/create.blade.php', '<div>Component</div>');
file_put_contents($this->projectRoot.'/'.$componentDirectory.'/create.php', '<?php');
file_put_contents($this->projectRoot.'/'.$componentDirectory.'/create.js', '// js');
$graph = new Graph($this->projectRoot);
$graph->link('tests/Feature/ComponentTest.php', 'storage/framework/views/test_7/livewire/'.str_replace('{hash}', $hash, $generated));
$graph->link('tests/Feature/UnrelatedTest.php', 'storage/framework/views/test_8/livewire/views/deadbeef.blade.php');
expect($graph->affected([$componentDirectory.'/'.$sibling]))->toBe(['tests/Feature/ComponentTest.php']);
})->with([
'class sibling via the generated class' => ['create.php', 'classes/{hash}.php'],
'class sibling via the generated view' => ['create.php', 'views/{hash}.blade.php'],
'asset sibling via the generated view' => ['create.js', 'views/{hash}.blade.php'],
]);
it('preserves direct view edges for class-based components', function (): void {
$viewPath = 'resources/views/livewire/create-post.blade.php';
@@ -279,7 +299,6 @@ describe('markKnownTestFiles()', function (): void {
$graph->markKnownTestFiles(['tests/Feature/UserTest.php']);
// The pre-existing edge survives — the test still depends on the source file.
$affected = $graph->affected(['app/Models/User.php']);
expect($affected)->toContain('tests/Feature/UserTest.php');
@@ -3,11 +3,6 @@
use Pest\Plugins\Tia;
test('does not throw when an integer --random-order-seed is passed as a separate argv element', function (): void {
// Mirrors the parallel worker argv (see bin/worker.php), where
// `--random-order-seed` and its value arrive as separate items and the
// seed value is an int rather than a string. Regression test for the
// str_starts_with() TypeError in Tia::argumentPresent() — the same class
// of bug as #1206, which was only fixed in HandleArguments.
$arguments = ['--order-by=random', '--random-order-seed', 1782350398];
expect(Tia::isEnabledForRun($arguments))->toBeFalse();
-1
View File
@@ -38,7 +38,6 @@ describe('activateLinkTracking()', function (): void {
$recorder->linkSource('/project/resources/views/welcome.blade.php');
$recorder->endTest();
// A second test must start cleanly — endTest resets state even with no driver.
$recorder->beginTest('Some\Missing\TestClass', 'second', '/project/tests/Feature/SecondTest.php');
$recorder->linkSource('/project/resources/views/about.blade.php');
$recorder->endTest();
-3
View File
@@ -78,9 +78,6 @@ it('keys a result per dataset row rather than per method', function (): void {
$collector->testSkipped('the fake driver does not report balances');
$collector->finishTest();
// Without the dataset in the key both rows write to `Class::method`, so the
// second one overwrites the first and a replay hands every row the same
// status — a passing row reported as skipped, or a failing one as passed.
expect(array_keys($collector->all()))->toBe([
'Tests\Feature\OrderTest::it prices an order#opp',
'Tests\Feature\OrderTest::it prices an order#fake',
@@ -48,10 +48,6 @@ describe('fromSql()', function (): void {
});
it('does not leak int keys for numeric identifiers', function (): void {
// `substring(x FROM 1 FOR 3)` is standard SQL, and the `1` matches the
// FROM pattern. Collecting names as array keys makes PHP coerce the
// numeric string to an int, which then violates the declared
// list<string> and blows up Recorder::linkTable(string).
expect(TableExtractor::fromSql('select substring(name from 1 for 3) from users'))
->each->toBeString();
});
@@ -99,9 +95,6 @@ describe('fromMigrationSource()', function (): void {
});
it('does not leak int keys for numeric table names', function (): void {
// A table named `123` is a legal quoted identifier. Collecting names as
// array keys makes PHP coerce it to an int, breaking the declared
// list<string>, so it must survive as a string rather than be dropped.
expect(TableExtractor::fromMigrationSource("DB::table('123')->insert([]);"))
->toBe(['123']);
});
-3
View File
@@ -57,9 +57,6 @@ describe('isTestFile()', function (): void {
->and($paths->isTestFile('tests/Unit/Helper.php'))->toBeTrue();
});
// Regression: a suffix of "Test.php" must match "ExampleTest.php". A previous
// normalisation prepended a dot (".Test.php"), which matched nothing and left
// edited tests looking unchanged to TIA, replaying stale results.
it('does not require a dot before the suffix', function (): void {
$paths = new TestPaths(
directories: ['tests/Unit'],
-1
View File
@@ -28,5 +28,4 @@ test('collision', function (array $arguments): void {
expect(implode("\n", $outputContent))->toMatchSnapshot();
})->with([
[['']],
// [['--parallel']],
])->skipOnWindows();
-1
View File
@@ -16,7 +16,6 @@ $run = function () {
$rawXmlContent = file_get_contents($junitLogFile);
unlink($junitLogFile);
// convert xml to array
try {
$xml = new SimpleXMLElement(preg_replace("/(<\/?)(\w+):([^>]*>)/", '$1$2$3', $rawXmlContent));
+2 -2
View File
@@ -26,13 +26,13 @@ test('parallel', function () use ($run): void {
$file = file_get_contents(__FILE__);
$file = preg_replace(
'/\$expected = \'.*?\';/',
"\$expected = '1 deprecated, 4 warnings, 5 incomplete, 3 notices, 40 todos, 27 skipped, 1540 passed (3343 assertions)';",
"\$expected = '1 deprecated, 4 warnings, 5 incomplete, 3 notices, 40 todos, 26 skipped, 1544 passed (3350 assertions)';",
$file,
);
file_put_contents(__FILE__, $file);
}
$expected = '1 deprecated, 4 warnings, 5 incomplete, 3 notices, 40 todos, 27 skipped, 1540 passed (3343 assertions)';
$expected = '1 deprecated, 4 warnings, 5 incomplete, 3 notices, 40 todos, 26 skipped, 1544 passed (3350 assertions)';
expect($output)
->toContain("Tests: {$expected}")