at the end of the day, it was inevitable

This commit is contained in:
Mo Elzubeir
2022-12-09 08:36:26 -06:00
commit 1218570914
1768 changed files with 887087 additions and 0 deletions
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace Tests\Helper;
/**
* Class AccessorTrait
* @package Tests\Helper
*/
trait AccessorTrait
{
/**
* Call specified method of given object.
*
* @param object $object Some object.
* @param string $method Called method name.
* @param array $arguments Method parameters.
*
* @return mixed
*/
public function call($object, $method, array $arguments = [])
{
$caller = function () use ($method, $arguments) {
return call_user_func_array([ $this, $method ], $arguments);
};
$caller = $caller->bindTo($object, $object);
return $caller();
}
}
+261
View File
@@ -0,0 +1,261 @@
<?php
namespace Tests\Helper;
use PHPUnit\Framework\TestCase;
use UserBundle\Entity\Notification\ThemeOption\ThemeOptionFont;
/**
* Class CssAssertBuilder
*
* @package Helper
*/
class CssAssertBuilder
{
const PROPERTY_WITH_VALUE_PATTERN_TPL = '/%s[^\{]*?\{[^\}]*%s:\s*%s[^\}]*\}/i';
const PROPERTY_PATTERN_TPL = '/%s[^\{]*?\{[^\}]*%s:[^\}]*\}/i';
private static $searchedCharacters = [
'.',
'[',
']',
'(',
')',
'{',
'}',
'/',
];
private static $replaceCharacters = [
'\.',
'\[',
'\]',
'\(',
'\)',
'\{',
'\}',
'\/',
];
/**
* @var string
*/
private $selector;
/**
* @var boolean
*/
private $shouldExists = true;
/**
* @var array
*/
private $asserts = [];
/**
* CssAssertBuilder constructor.
*
* @param string $selector A base css element selector.
* @param boolean $escape Should escape specific pattern symbols or not.
*/
public function __construct($selector, $escape = true)
{
if ($escape) {
$selector = str_replace(self::$searchedCharacters, self::$replaceCharacters, $selector);
}
$this->selector = $selector;
}
/**
* @return CssAssertBuilder
*/
public function shouldExists()
{
$this->shouldExists = true;
return $this;
}
/**
* @return CssAssertBuilder
*/
public function shouldNotExists()
{
$this->shouldExists = false;
return $this;
}
/**
* @param string $selector A base css element selector.
*
* @return CssAssertBuilder
*/
public static function create($selector)
{
return new CssAssertBuilder($selector);
}
/**
* @param ThemeOptionFont $font Font which should be rendered.
*
* @return CssAssertBuilder
*/
public function hasFont(ThemeOptionFont $font)
{
$this
->propertyShouldBe('font-family', $font->getFamily()->getCss())
->propertyShouldBe('font-size', $font->getSize());
$style = $font->getStyle();
if ($style->isBold()) {
$this->propertyShouldBe('font-weight', 'bold');
} else {
$this->propertyShouldNotBe('font-weight', 'bold');
}
if ($style->isItalic()) {
$this->propertyShouldBe('font-style', 'italic');
} else {
$this->propertyShouldNotBe('font-style', 'italic');
}
if ($style->isUnderline()) {
$this->propertyShouldBe('text-decoration', 'underline');
} else {
$this->propertyShouldNotBe('text-decoration', 'underline');
}
return $this;
}
/**
* @return static
*/
public function hasNotAnyFonts()
{
return $this
->propertyShouldNotExists('font-family')
->propertyShouldNotExists('font-size')
->propertyShouldNotExists('font-weight')
->propertyShouldNotExists('font-style')
->propertyShouldNotExists('text-decoration');
}
/**
* @param string $name Property name.
* @param string $message Error message.
*
* @return static
*/
public function propertyShouldExists($name, $message = '')
{
$this->asserts[] = [
'method' => 'assertRegExp',
'arguments' => [
sprintf(self::PROPERTY_PATTERN_TPL, $this->selector, $name),
'___',
$message,
],
];
return $this;
}
/**
* @param string $name Property name.
* @param string $message Error message.
*
* @return static
*/
public function propertyShouldNotExists($name, $message = '')
{
$this->asserts[] = [
'method' => 'assertNotRegExp',
'arguments' => [
sprintf(self::PROPERTY_PATTERN_TPL, $this->selector, $name),
'___',
$message,
],
];
return $this;
}
/**
* @param string $name Property name.
* @param string $value Expected property value.
* @param string $message Error message.
*
* @return static
*/
public function propertyShouldBe($name, $value, $message = '')
{
$name = str_replace(self::$searchedCharacters, self::$replaceCharacters, $name);
$value = str_replace(self::$searchedCharacters, self::$replaceCharacters, $value);
$this->asserts[] = [
'method' => 'assertRegExp',
'arguments' => [
sprintf(self::PROPERTY_WITH_VALUE_PATTERN_TPL, $this->selector, $name, $value),
'___',
$message,
],
];
return $this;
}
/**
* @param string $name Property name.
* @param string $value Expected property value.
* @param string $message Error message.
*
* @return static
*/
public function propertyShouldNotBe($name, $value = '', $message = '')
{
$name = str_replace(self::$searchedCharacters, self::$replaceCharacters, $name);
$value = str_replace(self::$searchedCharacters, self::$replaceCharacters, $value);
$this->asserts[] = [
'method' => 'assertNotRegExp',
'arguments' => [
sprintf(self::PROPERTY_WITH_VALUE_PATTERN_TPL, $this->selector, $name, $value),
'___',
$message,
],
];
return $this;
}
/**
* @param string $html HTML content.
*
* @return void
*/
public function assert($html)
{
if (! $this->shouldExists) {
TestCase::assertNotRegExp("/{$this->selector}/", $html);
// Don't assert property 'cause it's not necessary.
return;
}
foreach ($this->asserts as $config) {
$arguments = \nspl\a\map(function ($argument) use ($html) {
if (is_string($argument) && ($argument === '___')) {
$argument = $html;
}
return $argument;
}, $config['arguments']);
call_user_func_array([ TestCase::class, $config['method'] ], $arguments);
}
}
}
+67
View File
@@ -0,0 +1,67 @@
<?php
namespace Tests\Helper;
use PHPUnit\Framework\TestCase;
/**
* Class CssAsserter
*
* @package Helper
*/
class CssAsserter
{
/**
* @var string
*/
private $styles;
/**
* CssAsserter constructor.
*
* @param string $styles Raw css style text.
*/
public function __construct($styles)
{
$this->styles = $styles;
}
/**
* @param string $html Raw html.
*
* @return CssAsserter
*/
public static function createFromHtml($html)
{
$matches = [];
preg_match('#<style>([^<]*)</style>#i', $html, $matches);
array_shift($matches);
return new CssAsserter(implode("\n", $matches));
}
/**
* @param string $selector Css selector.
*
* @return CssAsserter
*/
public function hasSelector($selector)
{
TestCase::assertRegExp('/'.$selector.'/i', $this->styles);
return $this;
}
/**
* @param string $selector Css selector.
*
* @return CssPropertiesAsserter
*/
public function with($selector)
{
$this->hasSelector($selector);
return new CssPropertiesAsserter(preg_replace('/%s[^\{]*?\{([^\}]*?)\}/i', '$1', $this->styles), $this);
}
}
+130
View File
@@ -0,0 +1,130 @@
<?php
namespace Tests\Helper;
use PHPUnit\Framework\TestCase;
use UserBundle\Entity\Notification\ThemeOption\ThemeOptionFont;
/**
* Class CssPropertiesAsserter
*
* @package Helper
*/
class CssPropertiesAsserter
{
/**
* @var string
*/
private $properties;
/**
* @var CssAsserter
*/
private $cssAsserter;
/**
* CssAsserter constructor.
*
* @param string $properties Css properties.
* @param CssAsserter|null $cssAsserter A parent CssAsserter instance.
*/
public function __construct($properties, CssAsserter $cssAsserter)
{
$this->properties = $properties;
$this->cssAsserter = $cssAsserter;
}
/**
* @param string $name Property name.
* @param string|null $value Property value.
*
* @return CssPropertiesAsserter
*/
public function has($name, $value = null)
{
if ($value !== null) {
$value = str_replace([ '(', ')' ], [ '\(', '\)' ], $value);
}
$pattern = $value === null
? sprintf('/%s:\s*[^;];/i', $name)
: sprintf('/%s:\s*%s;/i', $name, $value);
TestCase::assertRegExp($pattern, $this->properties);
return $this;
}
/**
* @param string $name Property name.
* @param string|null $value Property value.
*
* @return CssPropertiesAsserter
*/
public function hasNot($name, $value = null)
{
$pattern = $value === null
? sprintf('/%s:\s*[^;];/i', $name)
: sprintf('/%s:\s*%s;/i', $name, $value);
TestCase::assertNotRegExp($pattern, $this->properties);
return $this;
}
/**
* @param ThemeOptionFont $font A ThemeOptionFont instance.
*
* @return CssPropertiesAsserter
*/
public function hasFont(ThemeOptionFont $font)
{
$this
->has('font-family', $font->getFamily()->getCss())
->has('font-size', $font->getSize());
$style = $font->getStyle();
if ($style->isBold()) {
$this->has('font-weight', 'bold');
} else {
$this->hasNot('font-weight');
}
if ($style->isItalic()) {
$this->has('font-style', 'italic');
} else {
$this->hasNot('font-style');
}
if ($style->isUnderline()) {
$this->has('text-decoration', 'underline');
} else {
$this->hasNot('text-decoration');
}
return $this;
}
/**
* @return CssPropertiesAsserter
*/
public function hasNotFontAtAll()
{
return $this
->hasNot('font-family')
->hasNot('font-size')
->hasNot('font-weight')
->hasNot('font-style')
->hasNot('text-decoration');
}
/**
* @return null|CssAsserter
*/
public function end()
{
return $this->cssAsserter;
}
}
+226
View File
@@ -0,0 +1,226 @@
<?php
namespace Tests\Helper;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DomCrawler\Crawler;
/**
* Class HtmlAsserter
*
* @package Helper
*/
class HtmlAsserter
{
/**
* @var Crawler
*/
private $root;
/**
* @var HtmlAsserter|null
*/
private $parent;
/**
* HtmlAsserter constructor.
*
* @param Crawler $root A Crawler instance.
* @param HtmlAsserter $parent A parent Crawler instance.
*/
public function __construct(Crawler $root, HtmlAsserter $parent = null)
{
$this->root = $root;
$this->parent = $parent;
}
/**
* @param string $selector Node selector.
* @param integer $count Expected node numbers. Check that at least one
* exists if -1.
*
* @return HtmlAsserter
*/
public function hasNode($selector, $count = 1)
{
$nodes = $this->root->filter($selector);
if ($count === -1) {
TestCase::assertGreaterThan(0, count($nodes), sprintf(
'Expects at least one node \'%s\' but got zero',
$selector
));
} else {
TestCase::assertCount($count, $nodes, sprintf(
'Expects %d of \'%s\' nodes but got another count',
$count,
$selector
));
}
return $this;
}
/**
* @param string $selector Node selector.
*
* @return HtmlAsserter
*/
public function hasNotNode($selector)
{
TestCase::assertCount(0, $this->root->filter($selector), sprintf(
'Node \'%s\' is exists but should\'nt',
$selector
));
return $this;
}
/**
* @param string $class Expected node class.
*
* @return HtmlAsserter
*/
public function hasClass($class)
{
TestCase::assertContains($class, $this->root->attr('class'), sprintf(
'Current node should has \'%s\' class but it has not',
$class
));
return $this;
}
/**
* @param string $name HTML node attribute name.
* @param string $value Expected value.
*
* @return HtmlAsserter
*/
public function hasAttr($name, $value = null)
{
$nodeValue = $this->root->attr($name);
if ($value === null) {
TestCase::assertNotNull($nodeValue, sprintf(
'Node attribute \'%s\' should exists but it has not',
$name
));
} else {
TestCase::assertEquals($value, $nodeValue, sprintf(
'Node attribute \'%s\' should match to \'%s\' but it has \'%s\'',
$name,
$value,
$nodeValue
));
}
return $this;
}
/**
* @param string $content Expected text content.
* @param boolean $strict Should content only specified values or not.
*
* @return HtmlAsserter
*/
public function contains($content, $strict = false)
{
$nodeContent = $this->root->getNode(0)->textContent;
if ($strict) {
TestCase::assertEquals($content, $nodeContent, sprintf(
'Node should contains only \'%s\' but it has not',
$content
));
} else {
TestCase::assertContains($content, $nodeContent, sprintf(
'Node should contains \'%s\' but it has not',
$content
));
}
return $this;
}
/**
* @param string $content Unexpected text content.
* @param boolean $strict Should content only specified values or not.
*
* @return $this
*/
public function notContains($content, $strict = false)
{
$nodeContent = $this->root->getNode(0)->textContent;
if ($strict) {
TestCase::assertNotEquals($content, $nodeContent, sprintf(
'Node should\'nt contains \'%s\' but it has',
$content
));
} else {
TestCase::assertNotContains($content, $nodeContent, sprintf(
'Node should\'nt contains \'%s\' but it has',
$content
));
}
return $this;
}
/**
* @param string $regex Regular expression.
*
* @return HtmlAsserter
*/
public function regexContent($regex)
{
TestCase::assertRegExp($regex, $this->root->getNode(0)->textContent, sprintf(
'Content of node should match to \'%s\' but it has not',
$regex
));
return $this;
}
/**
* @param string $selector Node selector.
*
* @return HtmlAsserter
*/
public function with($selector)
{
$this->hasNode($selector, -1);
return new static($this->root->filter($selector), $this);
}
/**
* @param integer $idx Child node index.
*
* @return HtmlAsserter
*/
public function child($idx)
{
return new static(new Crawler($this->root->getNode($idx)), $this);
}
/**
* @return HtmlAsserter
*/
public function end()
{
return $this->parent !== null ? $this->parent : $this;
}
/**
* @return HtmlAsserter
*/
public function dump()
{
echo $this->root->html();
return $this;
}
}