Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various new traits #5

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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 .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
vendor
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
}
],
"require": {
"php": "^8"
"php": "^8",
"drupal/core-utility": "^10 || ^11",
"symfony/validator": "^5 || ^6 || ^7"
},
"minimum-stability": "dev",
"prefer-stable": true,
Expand Down
49 changes: 49 additions & 0 deletions src/Traits/AssertViolationsTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace PNX\DrupalTestUtils\Traits;

use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationListInterface;

/**
* Defines a trait for asserting violations.
*/
trait AssertViolationsTrait {

/**
* Asserts that the expected violations were found.
*
* @param array $expected
* Expected violation messages keyed by propery paths.
* @param \Symfony\Component\Validator\ConstraintViolationListInterface $violations
* A list of violations.
*/
protected static function assertViolations(array $expected, ConstraintViolationListInterface $violations): void {
$list = [];
foreach ($violations as $violation) {
\assert($violation instanceof ConstraintViolation);
$list[$violation->getPropertyPath()] = \strip_tags((string) $violation->getMessage());
}
self::assertEquals($expected, $list);
}

/**
* Asserts that an expected violation exists.
*
* @param string $expected_violation
* Expected violation message.
* @param \Symfony\Component\Validator\ConstraintViolationListInterface $violations
* A list of violations.
*/
protected static function assertViolationExists(string $expected_violation, ConstraintViolationListInterface $violations): void {
$list = [];
foreach ($violations as $violation) {
\assert($violation instanceof ConstraintViolation);
$list[$violation->getPropertyPath()] = \strip_tags((string) $violation->getMessage());
}
self::assertContains($expected_violation, $list);
}

}
66 changes: 66 additions & 0 deletions src/Traits/RandomValuesTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

declare(strict_types=1);

namespace PNX\DrupalTestUtils\Traits;

use Drupal\Component\Utility\Random;
use Symfony\Component\Validator\ConstraintViolation;

/**
* Additional random value generation methods.
*/
trait RandomValuesTrait {

/**
* Generates a random URL.
*
* @return string
* Random URL.
*/
protected function randomUrl(): string {
$random = new Random();
return \sprintf('https://%s.com/%s', $random->name(), $random->name());
}
Comment on lines +15 to +24
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've always felt we should use example.com as the domain name. Turns out there is now a reserved .example TLD.

Suggested change
/**
* Generates a random URL.
*
* @return string
* Random URL.
*/
protected function randomUrl(): string {
$random = new Random();
return \sprintf('https://%s.com/%s', $random->name(), $random->name());
}
/**
* Generates a random URL.
*
* @return string
* Random URL.
*/
protected function randomUrl(): string {
$random = new Random();
return \sprintf('https://%s.example/%s', $random->name(), $random->name());
}


/**
* Generates a random email.
*
* @return string
* Random email.
*/
protected function randomEmail(): string {
$random = new Random();
return \sprintf('%s@%s.com', $random->name(), $random->name());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return \sprintf('%s@%s.com', $random->name(), $random->name());
return \sprintf('%s@%s.example', $random->name(), $random->name());

}

/**
* Generates a random lat lon pair.
*/
protected function randomLatLonPair(): string {
$lon = $this->randomPoint(-180, 180);
$lat = $this->randomPoint(-84, 84);
return \sprintf('POINT(%s %s)', $lon, $lat);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: floats are not strings

Suggested change
return \sprintf('POINT(%s %s)', $lon, $lat);
return \sprintf('POINT(%.05n %.05n)', $lon, $lat);

}

/**
* Generates a random lat/lon point.
*/
private function randomPoint(int $min, int $max): float {
$number = \mt_rand($min, $max);
$decimals = \mt_rand(1, \pow(10, 5)) / \pow(10, 5);
return \round($number + $decimals, 5);
}
Comment on lines +46 to +53
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also require PHP 8.3 and use Randomizer::getFloat.


/**
* Generates a random address.
*
* @return string
* Address.
*/
public function randomAddress(): string {
$random = new Random();
return \sprintf('%d %s St, %s, %d', \rand(1, 200), $random->name(), $random->name(), \rand(2000, 2999));
}

}
52 changes: 52 additions & 0 deletions src/Traits/SpinTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace PNX\DrupalTestUtils\Traits;

/**
* Defines a trait for executing a callable until it passes.
*/
trait SpinTrait {

/**
* Executes a callable until it returns TRUE.
*
* Executes executing a task until a condition is met.
Comment on lines +13 to +15
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Executes a callable until it returns TRUE.
*
* Executes executing a task until a condition is met.
* Executes a callable until it returns TRUE.

*
* @param callable $lambda
* Callable to evaluate until TRUE or count is reached.
* @param int $count
* (optional) Number of times to try, defaults to 10.
* @param bool $throw
* (optional) Throw, TRUE to throw if the condition is not met.
*
* @return bool
* TRUE if lambda evaluated true.
*
* @throws \Exception
* When the condition is not met.
*/
protected function spin(callable $lambda, $count = 10, $throw = TRUE): bool {
Comment on lines +19 to +30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

Suggested change
* @param int $count
* (optional) Number of times to try, defaults to 10.
* @param bool $throw
* (optional) Throw, TRUE to throw if the condition is not met.
*
* @return bool
* TRUE if lambda evaluated true.
*
* @throws \Exception
* When the condition is not met.
*/
protected function spin(callable $lambda, $count = 10, $throw = TRUE): bool {
* @param non-negative-int $count
* (optional) Number of times to try, defaults to 10.
* @param bool $throw
* (optional) Throw, TRUE to throw if the condition is not met.
*
* @return bool
* TRUE if lambda evaluated true.
*
* @throws \Exception
* When the condition is not met.
*/
protected function spin(callable $lambda, int $count = 10, bool $throw = TRUE): bool {

$passes = 0;
while ($passes < $count) {
try {
if ($lambda($this)) {
return TRUE;
}
}
catch (\Exception $e) {
// Do nothing.
}
Comment on lines +38 to +40
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-capturing catch:

Suggested change
catch (\Exception $e) {
// Do nothing.
}
catch (\Exception) {
// Do nothing.
}


\usleep(500000);
$passes++;
}
// Max reached.
if ($throw) {
throw new \Exception(\sprintf('Condition was not met after %d attempts', $count));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to have a more specific exception, maybe \Behat\Mink\Exception\ExpectationException.

}
return FALSE;
}

}