Skip to content

Commit 77df1c4

Browse files
author
Kirill Nesmeyanov
committed
Improve behat tests
1 parent 3535817 commit 77df1c4

File tree

15 files changed

+674
-337
lines changed

15 files changed

+674
-337
lines changed

behat.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ default:
55
- '%paths.base%/tests/Feature'
66
contexts:
77
# Executors
8-
- TypeLang\Mapper\Tests\Context\Execution\MapTypeContext
8+
- TypeLang\Mapper\Tests\Context\Assert\TypeCastAssertions
9+
- TypeLang\Mapper\Tests\Context\Assert\TypeMatchAssertions
10+
- TypeLang\Mapper\Tests\Context\Assert\TypeStatementAssertions
11+
- TypeLang\Mapper\Tests\Context\Assert\ValueAssertions
912
# Providers
1013
- TypeLang\Mapper\Tests\Context\Provider\ConfigurationContext
1114
- TypeLang\Mapper\Tests\Context\Provider\MappingContext
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TypeLang\Mapper\Tests\Context\Assert;
6+
7+
use Behat\Step\Then;
8+
use TypeLang\Mapper\Tests\Context\Context;
9+
use TypeLang\Mapper\Tests\Context\Provider\MappingContext;
10+
use TypeLang\Mapper\Tests\Context\Provider\TypeContext;
11+
12+
/**
13+
* @api
14+
* @see http://behat.org/en/latest/quick_start.html
15+
*/
16+
final class TypeCastAssertions extends Context
17+
{
18+
#[Then('/^cast of "(?P<input>.+?)" must return (?P<expected>.+?)$/')]
19+
public function thenCast(string $inputCode, string $expectedCode): void
20+
{
21+
$inputValue = eval(\sprintf('return %s;', $inputCode));
22+
23+
$type = $this->from(TypeContext::class)
24+
->getCurrent();
25+
26+
$context = $this->from(MappingContext::class)
27+
->setContextByValue($inputValue);
28+
29+
$values = $this->from(ValueAssertions::class);
30+
31+
try {
32+
$actualValue = $type->cast($inputValue, $context);
33+
34+
$values->assertCompareWithCode(
35+
expected: $expectedCode,
36+
actual: $actualValue,
37+
message: \vsprintf('Type %s expects "%s" to be "%s" after casting:', [
38+
$type::class,
39+
$inputCode,
40+
$expectedCode,
41+
]),
42+
);
43+
} catch (\Throwable $e) {
44+
$values->assertCompareWithCode(
45+
expected: $expectedCode,
46+
actual: $e,
47+
);
48+
}
49+
}
50+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TypeLang\Mapper\Tests\Context\Assert;
6+
7+
use Behat\Step\Then;
8+
use PHPUnit\Framework\Assert;
9+
use TypeLang\Mapper\Tests\Context\Context;
10+
use TypeLang\Mapper\Tests\Context\Provider\MappingContext;
11+
use TypeLang\Mapper\Tests\Context\Provider\TypeContext;
12+
13+
/**
14+
* @api
15+
* @see http://behat.org/en/latest/quick_start.html
16+
*/
17+
final class TypeMatchAssertions extends Context
18+
{
19+
#[Then('/^match of "(?P<value>.+?)" must return (?P<status>false|true)$/')]
20+
public function thenMatch(string $code, string $status): void
21+
{
22+
$value = eval(\sprintf('return %s;', $code));
23+
24+
$type = $this->from(TypeContext::class)
25+
->getCurrent();
26+
27+
$context = $this->from(MappingContext::class)
28+
->setContextByValue($value);
29+
30+
$actual = $type->match($value, $context);
31+
32+
$message = \vsprintf('Type %s expects matching of %s to be %s, got %s', [
33+
$type::class,
34+
$code,
35+
$status,
36+
$actual ? 'true' : 'false',
37+
]);
38+
39+
if (\strtolower($status) === 'true') {
40+
Assert::assertTrue($actual, $message);
41+
} else {
42+
Assert::assertFalse($actual, $message);
43+
}
44+
}
45+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TypeLang\Mapper\Tests\Context\Assert;
6+
7+
use Behat\Step\Then;
8+
use PHPUnit\Framework\Assert;
9+
use TypeLang\Mapper\Tests\Context\Context;
10+
use TypeLang\Mapper\Tests\Context\Provider\PlatformContext;
11+
use TypeLang\Mapper\Tests\Context\Provider\TypeContext;
12+
use TypeLang\Printer\PrettyPrinter;
13+
14+
/**
15+
* @api
16+
* @see http://behat.org/en/latest/quick_start.html
17+
*/
18+
final class TypeStatementAssertions extends Context
19+
{
20+
#[Then('/^the type must be defined$/')]
21+
public function thenTypeMustBeDefined(): void
22+
{
23+
$statement = $this->from(TypeContext::class)
24+
->getStatement();
25+
26+
$platform = $this->from(PlatformContext::class)
27+
->getCurrent();
28+
29+
foreach ($platform->getTypes() as $builder) {
30+
if ($builder->isSupported($statement)) {
31+
return;
32+
}
33+
}
34+
35+
Assert::fail(\vsprintf('The type "%s" is not defined in "%s" platform', [
36+
(new PrettyPrinter())->print($statement),
37+
$platform->getName(),
38+
]));
39+
}
40+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TypeLang\Mapper\Tests\Context\Assert;
6+
7+
use PHPUnit\Framework\Assert;
8+
use TypeLang\Mapper\Exception\Mapping\InvalidValueException;
9+
use TypeLang\Mapper\Tests\Context\Context;
10+
11+
/**
12+
* @api
13+
* @see http://behat.org/en/latest/quick_start.html
14+
*/
15+
final class ValueAssertions extends Context
16+
{
17+
public function assertCompareWithCode(string $expected, mixed $actual, string $message = ''): void
18+
{
19+
if (\str_starts_with($expected, '<error:') && \str_ends_with($expected, '>')) {
20+
$expected = \trim(\substr($expected, 7, -1));
21+
22+
Assert::assertInstanceOf(InvalidValueException::class, $actual);
23+
Assert::assertStringContainsString($expected, $actual->getMessage());
24+
25+
return;
26+
}
27+
28+
if ($actual instanceof \Throwable) {
29+
throw $actual;
30+
}
31+
32+
$expectedValue = eval(\sprintf('return %s;', $expected));
33+
34+
if (\is_float($expectedValue) && \is_nan($expectedValue)) {
35+
Assert::assertNan($actual, $message);
36+
} elseif (\is_object($expectedValue) || \is_object($actual)) {
37+
Assert::assertEquals($expectedValue, $actual, $message);
38+
} else {
39+
Assert::assertSame($expectedValue, $actual, $message);
40+
}
41+
}
42+
}

tests/Context/Execution/MapTypeContext.php

Lines changed: 0 additions & 105 deletions
This file was deleted.

tests/Context/Provider/ConfigurationContext.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace TypeLang\Mapper\Tests\Context\Provider;
66

7-
use PHPUnit\Framework\Assert;
87
use TypeLang\Mapper\Runtime\Configuration;
98
use TypeLang\Mapper\Runtime\ConfigurationInterface;
109
use TypeLang\Mapper\Tests\Context\Context;

tests/Context/Provider/PlatformContext.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ public function setCurrent(PlatformInterface $platform): PlatformInterface
4747
return $this->current = $platform;
4848
}
4949

50+
#[Given('/^platform "(?P<platform>[a-zA-Z0-9_\x80-\xff\\\\]+?)"$/')]
51+
public function givenPlatform(string $platform): void
52+
{
53+
// @phpstan-ignore-next-line
54+
$this->setCurrent(new $platform(
55+
$this->from(MetadataContext::class)
56+
->getDriver(),
57+
));
58+
}
59+
5060
#[Given('no platform')]
5161
#[Given('empty platform')]
5262
public function givenEmptyPlatform(): void

tests/Context/Provider/TypeContext.php

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use TypeLang\Mapper\Tests\Context\Context;
1010
use TypeLang\Mapper\Tests\Extension\ContextArgumentTransformerExtension\AsTestingContext;
1111
use TypeLang\Mapper\Type\TypeInterface;
12+
use TypeLang\Parser\Node\Stmt\TypeStatement;
1213

1314
/**
1415
* @api
@@ -19,6 +20,8 @@ final class TypeContext extends Context
1920
{
2021
private ?TypeInterface $current = null;
2122

23+
private ?TypeStatement $statement = null;
24+
2225
/**
2326
* @api
2427
*/
@@ -37,14 +40,41 @@ public function setCurrent(TypeInterface $type): TypeInterface
3740
return $this->current = $type;
3841
}
3942

40-
#[Given('/^type "(?P<type>[a-zA-Z0-9_\x80-\xff\\\\]+?)"$/')]
41-
public function givenType(string $type): void
43+
/**
44+
* @api
45+
*/
46+
public function getStatement(): TypeStatement
47+
{
48+
Assert::assertNotNull($this->statement, 'Type statement is not set');
49+
50+
return $this->statement;
51+
}
52+
53+
/**
54+
* @api
55+
*/
56+
public function setStatement(TypeStatement $type): TypeStatement
57+
{
58+
return $this->statement = $type;
59+
}
60+
61+
#[Given('/^type statement "(?P<type>.+?)"$/')]
62+
public function givenTypeStatement(string $type): void
63+
{
64+
$parser = $this->from(TypeParserContext::class)
65+
->getCurrent();
66+
67+
$this->setStatement($parser->getStatementByDefinition($type));
68+
}
69+
70+
#[Given('/^type "(?P<class>[a-zA-Z0-9_\x80-\xff\\\\]+?)"$/')]
71+
public function givenType(string $class): void
4272
{
43-
$this->givenTypeWith($type);
73+
$this->givenTypeWith($class);
4474
}
4575

46-
#[Given('/^type "(?P<type>[a-zA-Z0-9_\x80-\xff\\\\]+?)" with (?P<args>.+?)$/')]
47-
public function givenTypeWith(string $type, string $args = '{}'): void
76+
#[Given('/^type "(?P<class>[a-zA-Z0-9_\x80-\xff\\\\]+?)" with (?P<args>.+?)$/')]
77+
public function givenTypeWith(string $class, string $args = '{}'): void
4878
{
4979
try {
5080
$arguments = \json_decode($args, true, flags: \JSON_THROW_ON_ERROR);
@@ -53,6 +83,6 @@ public function givenTypeWith(string $type, string $args = '{}'): void
5383
}
5484

5585
// @phpstan-ignore-next-line
56-
$this->setCurrent(new $type(...$arguments));
86+
$this->setCurrent(new $class(...$arguments));
5787
}
5888
}

0 commit comments

Comments
 (0)