diff --git a/src/Exporters/Exporter.php b/src/Exporters/Exporter.php new file mode 100644 index 00000000..25c685b9 --- /dev/null +++ b/src/Exporters/Exporter.php @@ -0,0 +1,76 @@ +exporter = new BaseExporter(); + } + + /** + * Exports a value into a single-line string recursively. + * + * @param array $data + */ + public function shortenedRecursiveExport(array &$data, Context $context = null): string + { + $result = []; + $array = $data; + $itemsCount = 0; + $exporter = new self(); + $context ??= new Context(); + + $context->add($data); + + foreach ($array as $key => $value) { + if (++$itemsCount > self::MAX_ARRAY_ITEMS) { + $result[] = '…'; + + break; + } + + if (! is_array($value)) { + $result[] = $exporter->shortenedExport($value); + + continue; + } + + $result[] = $context->contains($data[$key]) !== false + ? '*RECURSION*' + : sprintf('[%s]', $this->shortenedRecursiveExport($data[$key], $context)); + } + + return implode(', ', $result); + } + + /** + * Exports a value into a single-line string. + */ + public function shortenedExport(mixed $value): string + { + return (string) preg_replace(['#\.{3}#', '#\\\n\s*#'], ['…'], $this->exporter->shortenedExport($value)); + } +} diff --git a/src/Repositories/DatasetsRepository.php b/src/Repositories/DatasetsRepository.php index 3b00b7b4..df7c71da 100644 --- a/src/Repositories/DatasetsRepository.php +++ b/src/Repositories/DatasetsRepository.php @@ -9,7 +9,7 @@ use Generator; use Pest\Exceptions\DatasetAlreadyExists; use Pest\Exceptions\DatasetDoesNotExist; use Pest\Exceptions\ShouldNotHappen; -use SebastianBergmann\Exporter\Exporter; +use Pest\Exporters\Exporter; use function sprintf; use Traversable; diff --git a/tests/.snapshots/success.txt b/tests/.snapshots/success.txt index fa1b24fc..d38b77ad 100644 --- a/tests/.snapshots/success.txt +++ b/tests/.snapshots/success.txt @@ -36,7 +36,7 @@ ✓ it sets arrays ✓ it gets bound to test case object with ('a') ✓ it gets bound to test case object with ('b') - ✓ it truncates the description with ('FoooFoooFoooFoooFoooFoooFoooF...ooFooo') + ✓ it truncates the description with ('FoooFoooFoooFoooFoooFoooFoooF…ooFooo') ✓ lazy datasets with (1) ✓ lazy datasets with (2) ✓ lazy datasets did the job right @@ -55,7 +55,7 @@ ✓ named datasets with data set "one" ✓ named datasets with data set "two" ✓ named datasets did the job right - ✓ lazy named datasets with (Bar Object (...)) + ✓ lazy named datasets with (Bar Object (…)) ✓ it creates unique test case names with ('Name 1', Pest\Plugin Object (), true) #1 ✓ it creates unique test case names with ('Name 1', Pest\Plugin Object (), true) #2 ✓ it creates unique test case names with ('Name 1', Pest\Plugin Object (), false) @@ -109,20 +109,20 @@ ✓ eager registered wrapped datasets with Generator functions did the job right ✓ eager registered wrapped datasets with Generator functions display description with data set "taylor" ✓ eager registered wrapped datasets with Generator functions display description with data set "james" - ✓ it can resolve a dataset after the test case is available with (Closure Object (...)) #1 - ✓ it can resolve a dataset after the test case is available with (Closure Object (...)) #2 - ✓ it can resolve a dataset after the test case is available with shared yield sets with (Closure Object (...)) #1 - ✓ it can resolve a dataset after the test case is available with shared yield sets with (Closure Object (...)) #2 - ✓ it can resolve a dataset after the test case is available with shared array sets with (Closure Object (...)) #1 - ✓ it can resolve a dataset after the test case is available with shared array sets with (Closure Object (...)) #2 - ✓ it resolves a potential bound dataset logically with ('foo', Closure Object (...)) - ✓ it resolves a potential bound dataset logically even when the closure comes first with (Closure Object (...), 'bar') - ✓ it will not resolve a closure if it is type hinted as a closure with (Closure Object (...)) #1 - ✓ it will not resolve a closure if it is type hinted as a closure with (Closure Object (...)) #2 - ✓ it will not resolve a closure if it is type hinted as a callable with (Closure Object (...)) #1 - ✓ it will not resolve a closure if it is type hinted as a callable with (Closure Object (...)) #2 - ✓ it can correctly resolve a bound dataset that returns an array with (Closure Object (...)) - ✓ it can correctly resolve a bound dataset that returns an array but wants to be spread with (Closure Object (...)) + ✓ it can resolve a dataset after the test case is available with (Closure Object (…)) #1 + ✓ it can resolve a dataset after the test case is available with (Closure Object (…)) #2 + ✓ it can resolve a dataset after the test case is available with shared yield sets with (Closure Object (…)) #1 + ✓ it can resolve a dataset after the test case is available with shared yield sets with (Closure Object (…)) #2 + ✓ it can resolve a dataset after the test case is available with shared array sets with (Closure Object (…)) #1 + ✓ it can resolve a dataset after the test case is available with shared array sets with (Closure Object (…)) #2 + ✓ it resolves a potential bound dataset logically with ('foo', Closure Object (…)) + ✓ it resolves a potential bound dataset logically even when the closure comes first with (Closure Object (…), 'bar') + ✓ it will not resolve a closure if it is type hinted as a closure with (Closure Object (…)) #1 + ✓ it will not resolve a closure if it is type hinted as a closure with (Closure Object (…)) #2 + ✓ it will not resolve a closure if it is type hinted as a callable with (Closure Object (…)) #1 + ✓ it will not resolve a closure if it is type hinted as a callable with (Closure Object (…)) #2 + ✓ it can correctly resolve a bound dataset that returns an array with (Closure Object (…)) + ✓ it can correctly resolve a bound dataset that returns an array but wants to be spread with (Closure Object (…)) ↓ forbids to define tests in Datasets dirs and Datasets.php files PASS Tests\Features\Depends @@ -549,7 +549,7 @@ ✓ it passes with ('Fortaleza') ✓ it passes with ('Sollefteå') ✓ it passes with ('Ιεράπετρα') - ✓ it passes with (stdClass Object (...)) + ✓ it passes with (stdClass Object (…)) ✓ it passes with array ✓ it passes with *not* ✓ it properly fails with *not* @@ -689,7 +689,7 @@ ✓ uses dataset with (3) ✓ uses dataset with (4) ✓ uses dataset with (5) - ✓ uses dataset with ('ScopedDatasets/NestedDirector...ts.php') + ✓ uses dataset with ('ScopedDatasets/NestedDirector…ts.php') ✓ the right dataset is taken PASS Tests\Features\ScopedDatasets\Directory\NestedDirectory2\TestFileInNestedDirectory @@ -833,6 +833,8 @@ ✓ it show only the names of multiple named datasets in their description ✓ it show the actual dataset of multiple non-named datasets in their description ✓ it show the correct description for mixed named and not-named datasets + ✓ it shows the correct description for long texts with newlines + ✓ it shows the correct description for arrays with many elements PASS Tests\Unit\Expectations\OppositeExpectation ✓ it throw expectation failed exception with string argument @@ -858,24 +860,24 @@ ✓ it cannot resolve a parameter without type PASS Tests\Unit\Support\DatasetInfo - ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Datase...rs.php', true) + ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Datase…rs.php', true) ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Datasets.php', false) - ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Featur...rs.php', true) - ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Featur...rs.php', false) - ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Featur...ts.php', false) - ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Datase...rs.php', false) + ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Featur…rs.php', true) + ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Featur…rs.php', false) + ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Featur…ts.php', false) + ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Datase…rs.php', false) ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Datasets.php', true) - ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Featur...rs.php', false) #1 - ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Featur...rs.php', false) #2 - ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Featur...ts.php', true) - ✓ it computes the dataset scope with ('/var/www/project/tests/Datase...rs.php', '/var/www/project/tests') + ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Featur…rs.php', false) #1 + ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Featur…rs.php', false) #2 + ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Featur…ts.php', true) + ✓ it computes the dataset scope with ('/var/www/project/tests/Datase…rs.php', '/var/www/project/tests') ✓ it computes the dataset scope with ('/var/www/project/tests/Datasets.php', '/var/www/project/tests') - ✓ it computes the dataset scope with ('/var/www/project/tests/Featur...rs.php', '/var/www/project/tests/Features') - ✓ it computes the dataset scope with ('/var/www/project/tests/Featur...rs.php', '/var/www/project/tests/Featur...rs.php') #1 - ✓ it computes the dataset scope with ('/var/www/project/tests/Featur...ts.php', '/var/www/project/tests/Features') - ✓ it computes the dataset scope with ('/var/www/project/tests/Featur...rs.php', '/var/www/project/tests/Featur...ollers') - ✓ it computes the dataset scope with ('/var/www/project/tests/Featur...rs.php', '/var/www/project/tests/Featur...rs.php') #2 - ✓ it computes the dataset scope with ('/var/www/project/tests/Featur...ts.php', '/var/www/project/tests/Featur...ollers') + ✓ it computes the dataset scope with ('/var/www/project/tests/Featur…rs.php', '/var/www/project/tests/Features') + ✓ it computes the dataset scope with ('/var/www/project/tests/Featur…rs.php', '/var/www/project/tests/Featur…rs.php') #1 + ✓ it computes the dataset scope with ('/var/www/project/tests/Featur…ts.php', '/var/www/project/tests/Features') + ✓ it computes the dataset scope with ('/var/www/project/tests/Featur…rs.php', '/var/www/project/tests/Featur…ollers') + ✓ it computes the dataset scope with ('/var/www/project/tests/Featur…rs.php', '/var/www/project/tests/Featur…rs.php') #2 + ✓ it computes the dataset scope with ('/var/www/project/tests/Featur…ts.php', '/var/www/project/tests/Featur…ollers') PASS Tests\Unit\Support\Reflection ✓ it gets file name from closure @@ -917,4 +919,5 @@ PASS Tests\Visual\Version ✓ visual snapshot of help command output - Tests: 4 incomplete, 4 todos, 18 skipped, 634 passed (1554 assertions) \ No newline at end of file + Tests: 4 incomplete, 4 todos, 18 skipped, 627 passed (1514 assertions) + diff --git a/tests/Unit/DatasetsTests.php b/tests/Unit/DatasetsTests.php index a1914f82..63653f5b 100644 --- a/tests/Unit/DatasetsTests.php +++ b/tests/Unit/DatasetsTests.php @@ -23,7 +23,7 @@ it('show the actual dataset of non-named datasets in their description', functio ], __FILE__)); expect($descriptions[0])->toBe('(1)'); - expect($descriptions[1])->toBe('(array(2))'); + expect($descriptions[1])->toBe('([2])'); }); it('show only the names of multiple named datasets in their description', function () { @@ -57,9 +57,9 @@ it('show the actual dataset of multiple non-named datasets in their description' ], __FILE__)); expect($descriptions[0])->toBe('(1) / (3)'); - expect($descriptions[1])->toBe('(1) / (array(4))'); - expect($descriptions[2])->toBe('(array(2)) / (3)'); - expect($descriptions[3])->toBe('(array(2)) / (array(4))'); + expect($descriptions[1])->toBe('(1) / ([4])'); + expect($descriptions[2])->toBe('([2]) / (3)'); + expect($descriptions[3])->toBe('([2]) / ([4])'); }); it('show the correct description for mixed named and not-named datasets', function () { @@ -76,6 +76,26 @@ it('show the correct description for mixed named and not-named datasets', functi expect($descriptions[0])->toBe('data set "one" / (3)'); expect($descriptions[1])->toBe('data set "one" / data set "four"'); - expect($descriptions[2])->toBe('(array(2)) / (3)'); - expect($descriptions[3])->toBe('(array(2)) / data set "four"'); + expect($descriptions[2])->toBe('([2]) / (3)'); + expect($descriptions[3])->toBe('([2]) / data set "four"'); +}); + +it('shows the correct description for long texts with newlines', function () { + $descriptions = array_keys(DatasetsRepository::resolve([ + [ + ['some very \nlong text with \n newlines'], + ], + ], __FILE__)); + + expect($descriptions[0])->toBe('(\'some very long text with …wlines\')'); +}); + +it('shows the correct description for arrays with many elements', function () { + $descriptions = array_keys(DatasetsRepository::resolve([ + [ + [[1, 2, 3, 4, 5]], + ], + ], __FILE__)); + + expect($descriptions[0])->toBe('([1, 2, 3, …])'); });