This commit is contained in:
2020-10-06 14:27:47 +07:00
commit 586be80cf6
16613 changed files with 3274099 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
<?php
use \Codeception\Util\Annotation;
/**
* Class AnnotationTest
*
* @author davert
* @tag codeception
* @tag tdd
*/
class AnnotationTest extends \PHPUnit\Framework\TestCase
{
public function testClassAnnotation()
{
$this->assertEquals('davert', Annotation::forClass(__CLASS__)->fetch('author'));
$this->assertEquals('codeception', Annotation::forClass(__CLASS__)->fetch('tag'));
}
/**
* @param $var1
* @param $var2
* @return null
*/
public function testMethodAnnotation()
{
$this->assertEquals('null', Annotation::forClass(__CLASS__)
->method('testMethodAnnotation')
->fetch('return'));
}
public function testMultipleClassAnnotations()
{
$this->assertEquals(array('codeception', 'tdd'), Annotation::forClass(__CLASS__)->fetchAll('tag'));
}
public function testMultipleMethodAnnotations()
{
$this->assertEquals(
array('$var1', '$var2'),
Annotation::forClass(__CLASS__)->method('testMethodAnnotation')->fetchAll('param')
);
}
public function testGetAnnotationsFromDocBlock()
{
$docblock = <<<EOF
@user davert
@param key1
@param key2
EOF;
$this->assertEquals(['davert'], Annotation::fetchAnnotationsFromDocblock('user', $docblock));
$this->assertEquals(['key1', 'key2'], Annotation::fetchAnnotationsFromDocblock('param', $docblock));
}
public function testGetAllAnnotationsFromDocBlock()
{
$docblock = <<<EOF
@user davert
@param key1
@param key2
EOF;
$all = Annotation::fetchAllAnnotationsFromDocblock($docblock);
codecept_debug($all);
$this->assertEquals([
'user' => ['davert'],
'param' => ['key1', 'key2']
], Annotation::fetchAllAnnotationsFromDocblock($docblock));
}
public function testValueToSupportJson()
{
$values = Annotation::arrayValue('{ "code": "200", "user": "davert", "email": "davert@gmail.com" }');
$this->assertEquals(['code' => '200', 'user' => 'davert', 'email' => 'davert@gmail.com'], $values);
}
public function testValueToSupportAnnotationStyle()
{
$values = Annotation::arrayValue('( code="200", user="davert", email = "davert@gmail.com")');
$this->assertEquals(['code' => '200', 'user' => 'davert', 'email' => 'davert@gmail.com'], $values);
}
}

View File

@@ -0,0 +1,267 @@
<?php
namespace Codeception\Util;
class ArrayContainsComparatorTest extends \Codeception\Test\Unit
{
/**
* @var ArrayContainsComparator
*/
protected $ary;
protected function _before()
{
$this->ary = new ArrayContainsComparator(
[
'ticket' => [
'title' => 'Bug should be fixed',
'user' => ['name' => 'Davert'],
'labels' => null
]
]
);
}
// tests
public function testInclusion()
{
$this->assertTrue($this->ary->containsArray(['name' => 'Davert']));
$this->assertTrue($this->ary->containsArray(['user' => ['name' => 'Davert']]));
$this->assertTrue($this->ary->containsArray(['ticket' => ['title' => 'Bug should be fixed']]));
$this->assertTrue($this->ary->containsArray(['ticket' => ['user' => ['name' => 'Davert']]]));
$this->assertTrue($this->ary->containsArray(['ticket' => ['labels' => null]]));
}
/**
* @Issue https://github.com/Codeception/Codeception/issues/2070
*/
public function testContainsArrayComparesArrayWithMultipleZeroesCorrectly()
{
$comparator = new ArrayContainsComparator([
'responseCode' => 0,
'message' => 'OK',
'data' => [9, 0, 0],
]);
$expectedArray = [
'responseCode' => 0,
'message' => 'OK',
'data' => [0, 0, 0],
];
$this->assertFalse($comparator->containsArray($expectedArray));
}
public function testContainsArrayComparesArrayWithMultipleIdenticalSubArraysCorrectly()
{
$comparator = new ArrayContainsComparator([
'responseCode' => 0,
'message' => 'OK',
'data' => [[9], [0], [0]],
]);
$expectedArray = [
'responseCode' => 0,
'message' => 'OK',
'data' => [[0], [0], [0]],
];
$this->assertFalse($comparator->containsArray($expectedArray));
}
public function testContainsArrayComparesArrayWithValueRepeatedMultipleTimesCorrectlyNegativeCase()
{
$comparator = new ArrayContainsComparator(['foo', 'foo', 'bar']);
$expectedArray = ['foo', 'foo', 'foo'];
$this->assertFalse($comparator->containsArray($expectedArray));
}
public function testContainsArrayComparesArrayWithValueRepeatedMultipleTimesCorrectlyPositiveCase()
{
$comparator = new ArrayContainsComparator(['foo', 'foo', 'bar']);
$expectedArray = ['foo', 'bar', 'foo'];
$this->assertTrue($comparator->containsArray($expectedArray));
}
/**
* @issue https://github.com/Codeception/Codeception/issues/2630
*/
public function testContainsArrayComparesNestedSequentialArraysCorrectlyWhenSecondValueIsTheSame()
{
$array = [
['2015-09-10', 'unknown-date-1'],
['2015-10-10', 'unknown-date-1'],
];
$comparator = new ArrayContainsComparator($array);
$this->assertTrue($comparator->containsArray($array));
}
/**
* @issue https://github.com/Codeception/Codeception/issues/2630
* @codingStandardsIgnoreStart
*/
public function testContainsArrayComparesNestedSequentialArraysCorrectlyWhenSecondValueIsTheSameButOrderOfItemsIsDifferent()
{
// @codingStandardsIgnoreEnd
$comparator = new ArrayContainsComparator([
[
"2015-09-10",
"unknown-date-1"
],
[
"2015-10-10",
"unknown-date-1"
]
]);
$expectedArray = [
["2015-10-10", "unknown-date-1"],
["2015-09-10", "unknown-date-1"],
];
$this->assertTrue($comparator->containsArray($expectedArray));
}
/**
* @issue https://github.com/Codeception/Codeception/issues/2630
*/
public function testContainsArrayComparesNestedSequentialArraysCorrectlyWhenSecondValueIsDifferent()
{
$comparator = new ArrayContainsComparator([
[
"2015-09-10",
"unknown-date-1"
],
[
"2015-10-10",
"unknown-date-2"
]
]);
$expectedArray = [
["2015-09-10", "unknown-date-1"],
["2015-10-10", "unknown-date-2"],
];
$this->assertTrue($comparator->containsArray($expectedArray));
}
/**
* @issue https://github.com/Codeception/Codeception/issues/2630
*/
public function testContainsArrayComparesNestedSequentialArraysCorrectlyWhenJsonHasMoreItemsThanExpectedArray()
{
$comparator = new ArrayContainsComparator([
[
"2015-09-10",
"unknown-date-1"
],
[
"2015-10-02",
"unknown-date-1"
],
[
"2015-10-10",
"unknown-date-2"
]
]);
$expectedArray = [
["2015-09-10", "unknown-date-1"],
["2015-10-10", "unknown-date-2"],
];
$this->assertTrue($comparator->containsArray($expectedArray));
}
/**
* @issue https://github.com/Codeception/Codeception/pull/2635
*/
public function testContainsMatchesSuperSetOfExpectedAssociativeArrayInsideSequentialArray()
{
$comparator = new ArrayContainsComparator([[
'id' => '1',
'title' => 'Game of Thrones',
'body' => 'You are so awesome',
'created_at' => '2015-12-16 10:42:20',
'updated_at' => '2015-12-16 10:42:20',
]]);
$expectedArray = [['id' => '1']];
$this->assertTrue($comparator->containsArray($expectedArray));
}
/**
* @issue https://github.com/Codeception/Codeception/issues/2630
*/
public function testContainsArrayWithUnexpectedLevel()
{
$comparator = new ArrayContainsComparator([
"level1" => [
"level2irrelevant" => [],
"level2" => [
[
"level3" => [
[
"level5irrelevant1" => "a1",
"level5irrelevant2" => "a2",
"level5irrelevant3" => "a3",
"level5irrelevant4" => "a4",
"level5irrelevant5" => "a5",
"level5irrelevant6" => "a6",
"level5irrelevant7" => "a7",
"level5irrelevant8" => "a8",
"int1" => 1
]
],
"level3irrelevant" => [
"level4irrelevant" => 1
]
],
[
"level3" => [
[
"level5irrelevant1" => "b1",
"level5irrelevant2" => "b2",
"level5irrelevant3" => "b3",
"level5irrelevant4" => "b4",
"level5irrelevant5" => "b5",
"level5irrelevant6" => "b6",
"level5irrelevant7" => "b7",
"level5irrelevant8" => "b8",
"int1" => 1
]
],
"level3irrelevant" => [
"level4irrelevant" => 2
]
]
]
]
]);
$expectedArray = [
'level1' => [
'level2' => [
[
'int1' => 1,
],
[
'int1' => 1,
],
]
]
];
$this->assertTrue(
$comparator->containsArray($expectedArray),
"- <info>" . var_export($expectedArray, true) . "</info>\n"
. "+ " . var_export($comparator->getHaystack(), true)
);
}
/**
* Simplified testcase for issue reproduced by testContainsArrayWithUnexpectedLevel
*/
public function testContainsArrayComparesSequentialArraysHavingDuplicateSubArraysCorrectly()
{
$comparator = new ArrayContainsComparator([[1],[1]]);
$expectedArray = [[1],[1]];
$this->assertTrue(
$comparator->containsArray($expectedArray),
"- <info>" . var_export($expectedArray, true) . "</info>\n"
. "+ " . var_export($comparator->getHaystack(), true)
);
}
}

View File

@@ -0,0 +1,81 @@
<?php
require_once 'MockAutoload.php';
use Codeception\Util\MockAutoload as Autoload;
class AutoloadTest extends \PHPUnit\Framework\TestCase
{
protected function setUp()
{
Autoload::setFiles([
'/vendor/foo.bar/src/ClassName.php',
'/vendor/foo.bar/src/DoomClassName.php',
'/vendor/foo.bar/tests/ClassNameTest.php',
'/vendor/foo.bardoom/src/ClassName.php',
'/vendor/foo.bar.baz.dib/src/ClassName.php',
'/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php',
'/vendor/src/ClassName.php',
'/vendor/src/Foo/Bar/AnotherClassName.php',
'/vendor/src/Bar/Baz/ClassName.php',
]);
Autoload::addNamespace('Foo\Bar', '/vendor/foo.bar/src');
Autoload::addNamespace('Foo\Bar', '/vendor/foo.bar/tests');
Autoload::addNamespace('Foo\BarDoom', '/vendor/foo.bardoom/src');
Autoload::addNamespace('Foo\Bar\Baz\Dib', '/vendor/foo.bar.baz.dib/src');
Autoload::addNamespace('Foo\Bar\Baz\Dib\Zim\Gir', '/vendor/foo.bar.baz.dib.zim.gir/src');
Autoload::addNamespace('', '/vendor/src');
}
public function testExistingFile()
{
$actual = Autoload::load('Foo\Bar\ClassName');
$expect = '/vendor/foo.bar/src/ClassName.php';
$this->assertSame($expect, $actual);
$actual = Autoload::load('Foo\Bar\ClassNameTest');
$expect = '/vendor/foo.bar/tests/ClassNameTest.php';
$this->assertSame($expect, $actual);
}
public function testMissingFile()
{
$actual = Autoload::load('No_Vendor\No_Package\NoClass');
$this->assertFalse($actual);
}
public function testDeepFile()
{
$actual = Autoload::load('Foo\Bar\Baz\Dib\Zim\Gir\ClassName');
$expect = '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php';
$this->assertSame($expect, $actual);
}
public function testConfusion()
{
$actual = Autoload::load('Foo\Bar\DoomClassName');
$expect = '/vendor/foo.bar/src/DoomClassName.php';
$this->assertSame($expect, $actual);
$actual = Autoload::load('Foo\BarDoom\ClassName');
$expect = '/vendor/foo.bardoom/src/ClassName.php';
$this->assertSame($expect, $actual);
}
public function testEmptyPrefix()
{
$actual = Autoload::load('ClassName');
$expect = '/vendor/src/ClassName.php';
$this->assertSame($expect, $actual);
$actual = Autoload::load('Foo\Bar\AnotherClassName');
$expect = '/vendor/src/Foo/Bar/AnotherClassName.php';
$this->assertSame($expect, $actual);
$actual = Autoload::load('Bar\Baz\ClassName');
$expect = '/vendor/src/Bar/Baz/ClassName.php';
$this->assertSame($expect, $actual);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Codeception\Util;
class HttpCodeTest extends \Codeception\Test\Unit
{
public function testHttpCodeConstants()
{
$this->assertEquals(200, HttpCode::OK);
$this->assertEquals(404, HttpCode::NOT_FOUND);
}
public function testHttpCodeWithDescription()
{
$this->assertEquals('200 (OK)', HttpCode::getDescription(200));
$this->assertEquals('301 (Moved Permanently)', HttpCode::getDescription(301));
$this->assertEquals('401 (Unauthorized)', HttpCode::getDescription(401));
}
}

View File

@@ -0,0 +1,105 @@
<?php
namespace Codeception\Util;
class JsonArrayTest extends \Codeception\Test\Unit
{
/**
* @var JsonArray
*/
protected $jsonArray;
protected function _before()
{
$this->jsonArray = new JsonArray(
'{"ticket": {"title": "Bug should be fixed", "user": {"name": "Davert"}, "labels": null}}'
);
}
public function testXmlConversion()
{
$this->assertContains(
'<ticket><title>Bug should be fixed</title><user><name>Davert</name></user><labels></labels></ticket>',
$this->jsonArray->toXml()->saveXML()
);
}
public function testXmlArrayConversion2()
{
$jsonArray = new JsonArray(
'[{"user":"Blacknoir","age":27,"tags":["wed-dev","php"]},'
. '{"user":"John Doe","age":27,"tags":["web-dev","java"]}]'
);
$this->assertContains('<tags>wed-dev</tags>', $jsonArray->toXml()->saveXML());
$this->assertEquals(2, $jsonArray->filterByXPath('//user')->length);
}
public function testXPathLocation()
{
$this->assertGreaterThan(0, $this->jsonArray->filterByXPath('//ticket/title')->length);
$this->assertGreaterThan(0, $this->jsonArray->filterByXPath('//ticket/user/name')->length);
$this->assertGreaterThan(0, $this->jsonArray->filterByXPath('//user/name')->length);
}
public function testJsonPathLocation()
{
$this->assertNotEmpty($this->jsonArray->filterByJsonPath('$..user'));
$this->assertNotEmpty($this->jsonArray->filterByJsonPath('$.ticket.user.name'));
$this->assertNotEmpty($this->jsonArray->filterByJsonPath('$..user.name'));
$this->assertEquals(['Davert'], $this->jsonArray->filterByJsonPath('$.ticket.user.name'));
$this->assertEmpty($this->jsonArray->filterByJsonPath('$..invalid'));
}
/**
* @issue https://github.com/Codeception/Codeception/issues/2535
*/
public function testThrowsInvalidArgumentExceptionIfJsonIsInvalid()
{
$this->setExpectedException('InvalidArgumentException');
new JsonArray('{"test":');
}
/**
* @issue https://github.com/Codeception/Codeception/issues/4944
*/
public function testConvertsBareJson()
{
$jsonArray = new JsonArray('"I am a {string}."');
$this->assertEquals(['I am a {string}.'], $jsonArray->toArray());
}
/**
* @Issue https://github.com/Codeception/Codeception/issues/2899
*/
public function testInvalidXmlTag()
{
$jsonArray = new JsonArray('{"a":{"foo/bar":1,"":2},"b":{"foo/bar":1,"":2},"baz":2}');
$expectedXml = '<a><invalidTag1>1</invalidTag1><invalidTag2>2</invalidTag2></a>'
. '<b><invalidTag1>1</invalidTag1><invalidTag2>2</invalidTag2></b><baz>2</baz>';
$this->assertContains($expectedXml, $jsonArray->toXml()->saveXML());
}
public function testConvertsArrayHavingSingleElement()
{
$jsonArray = new JsonArray('{"success": 1}');
$expectedXml = '<?xml version="1.0" encoding="UTF-8"?>'
. "\n<root><success>1</success></root>\n";
$this->assertEquals($expectedXml, $jsonArray->toXml()->saveXML());
}
public function testConvertsArrayHavingTwoElements()
{
$jsonArray = new JsonArray('{"success": 1, "info": "test"}');
$expectedXml = '<?xml version="1.0" encoding="UTF-8"?>'
. "\n<root><success>1</success><info>test</info></root>\n";
$this->assertEquals($expectedXml, $jsonArray->toXml()->saveXML());
}
public function testConvertsArrayHavingSingleSubArray()
{
$jsonArray = new JsonArray('{"array": {"success": 1}}');
$expectedXml = '<?xml version="1.0" encoding="UTF-8"?>'
. "\n<array><success>1</success></array>\n";
$this->assertEquals($expectedXml, $jsonArray->toXml()->saveXML());
}
}

View File

@@ -0,0 +1,207 @@
<?php
namespace Codeception\Util;
class JsonTypeTest extends \Codeception\Test\Unit
{
protected $types = [
'id' => 'integer:>10',
'retweeted' => 'Boolean',
'in_reply_to_screen_name' => 'null|string',
'name' => 'string|null', // http://codeception.com/docs/modules/REST#seeResponseMatchesJsonType
'user' => [
'url' => 'String:url'
]
];
protected $data = [
'id' => 11,
'retweeted' => false,
'in_reply_to_screen_name' => null,
'name' => null,
'user' => ['url' => 'http://davert.com']
];
public function _after()
{
JsonType::cleanCustomFilters();
}
public function testMatchBasicTypes()
{
$jsonType = new JsonType($this->data);
$this->assertTrue($jsonType->matches($this->types));
}
public function testNotMatchesBasicType()
{
$this->data['in_reply_to_screen_name'] = true;
$jsonType = new JsonType($this->data);
$this->assertContains('`in_reply_to_screen_name: true` is of type', $jsonType->matches($this->types));
}
public function testIntegerFilter()
{
$jsonType = new JsonType($this->data);
$this->assertContains('`id: 11` is of type', $jsonType->matches(['id' => 'integer:<5']));
$this->assertContains('`id: 11` is of type', $jsonType->matches(['id' => 'integer:>15']));
$this->assertTrue($jsonType->matches(['id' => 'integer:=11']));
$this->assertTrue($jsonType->matches(['id' => 'integer:>5']));
$this->assertTrue($jsonType->matches(['id' => 'integer:>5:<12']));
$this->assertNotTrue($jsonType->matches(['id' => 'integer:>5:<10']));
}
public function testUrlFilter()
{
$this->data['user']['url'] = 'invalid_url';
$jsonType = new JsonType($this->data);
$this->assertNotTrue($jsonType->matches($this->types));
}
public function testRegexFilter()
{
$jsonType = new JsonType(['numbers' => '1-2-3']);
$this->assertTrue($jsonType->matches(['numbers' => 'string:regex(~1-2-3~)']));
$this->assertTrue($jsonType->matches(['numbers' => 'string:regex(~\d-\d-\d~)']));
$this->assertNotTrue($jsonType->matches(['numbers' => 'string:regex(~^\d-\d$~)']));
$jsonType = new JsonType(['published' => 1]);
$this->assertTrue($jsonType->matches(['published' => 'integer:regex(~1~)']));
$this->assertTrue($jsonType->matches(['published' => 'integer:regex(~1|2~)']));
$this->assertTrue($jsonType->matches(['published' => 'integer:regex(~2|1~)']));
$this->assertNotTrue($jsonType->matches(['published' => 'integer:regex(~2~)']));
$this->assertNotTrue($jsonType->matches(['published' => 'integer:regex(~2|3~)']));
$this->assertNotTrue($jsonType->matches(['published' => 'integer:regex(~3|2~)']));
$jsonType = new JsonType(['date' => '2011-11-30T04:06:44Z']);
$this->assertTrue($jsonType->matches(['date' => 'string:regex(~2011-11-30T04:06:44Z|2011-11-30T05:07:00Z~)']));
$this->assertNotTrue(
$jsonType->matches(['date' => 'string:regex(~2015-11-30T04:06:44Z|2016-11-30T05:07:00Z~)'])
);
}
public function testDateTimeFilter()
{
$jsonType = new JsonType(['date' => '2011-11-30T04:06:44Z']);
$this->assertTrue($jsonType->matches(['date' => 'string:date']));
$jsonType = new JsonType(['date' => '2012-04-30T04:06:00.123Z']);
$this->assertTrue($jsonType->matches(['date' => 'string:date']));
$jsonType = new JsonType(['date' => '1931-01-05T04:06:03.1+05:30']);
$this->assertTrue($jsonType->matches(['date' => 'string:date']));
}
public function testEmailFilter()
{
$jsonType = new JsonType(['email' => 'davert@codeception.com']);
$this->assertTrue($jsonType->matches(['email' => 'string:email']));
$jsonType = new JsonType(['email' => 'davert.codeception.com']);
$this->assertNotTrue($jsonType->matches(['email' => 'string:email']));
}
public function testNegativeFilters()
{
$jsonType = new JsonType(['name' => 'davert', 'id' => 1]);
$this->assertTrue($jsonType->matches([
'name' => 'string:!date|string:!empty',
'id' => 'integer:!=0',
]));
}
public function testCustomFilters()
{
JsonType::addCustomFilter('slug', function ($value) {
return strpos($value, ' ') === false;
});
$jsonType = new JsonType(['title' => 'have a test', 'slug' => 'have-a-test']);
$this->assertTrue($jsonType->matches([
'slug' => 'string:slug'
]));
$this->assertNotTrue($jsonType->matches([
'title' => 'string:slug'
]));
JsonType::addCustomFilter('/len\((.*?)\)/', function ($value, $len) {
return strlen($value) == $len;
});
$this->assertTrue($jsonType->matches([
'slug' => 'string:len(11)'
]));
$this->assertNotTrue($jsonType->matches([
'slug' => 'string:len(7)'
]));
}
public function testArray()
{
$this->types['user'] = 'array';
$jsonType = new JsonType($this->data);
$this->assertTrue($jsonType->matches($this->types));
}
public function testNull()
{
$jsonType = new JsonType(json_decode('{
"id": 123456,
"birthdate": null,
"firstname": "John",
"lastname": "Doe"
}', true));
$this->assertTrue($jsonType->matches([
'birthdate' => 'string|null'
]));
$this->assertTrue($jsonType->matches([
'birthdate' => 'null'
]));
}
public function testOR()
{
$jsonType = new JsonType(json_decode('{
"type": "DAY"
}', true));
$this->assertTrue($jsonType->matches([
'type' => 'string:=DAY|string:=WEEK'
]));
$jsonType = new JsonType(json_decode('{
"type": "WEEK"
}', true));
$this->assertTrue($jsonType->matches([
'type' => 'string:=DAY|string:=WEEK'
]));
}
public function testCollection()
{
$jsonType = new JsonType([
['id' => 1],
['id' => 3],
['id' => 5]
]);
$this->assertTrue($jsonType->matches([
'id' => 'integer'
]));
$this->assertNotTrue($res = $jsonType->matches([
'id' => 'integer:<3'
]));
$this->assertContains('3` is of type `integer:<3', $res);
$this->assertContains('5` is of type `integer:<3', $res);
}
/**
* @issue https://github.com/Codeception/Codeception/issues/4517
*/
public function testMatchesArrayReturnedByFetchBoth()
{
$jsonType = new JsonType([
'0' => 10,
'a' => 10,
'1' => 11,
'b' => 11,
]);
$this->assertTrue($jsonType->matches([
'a' => 'integer',
'b' => 'integer',
]));
}
}

View File

@@ -0,0 +1,110 @@
<?php
use Codeception\Util\Locator;
use Facebook\WebDriver\WebDriverBy;
class LocatorTest extends \PHPUnit\Framework\TestCase
{
public function testCombine()
{
$result = Locator::combine('//button[@value="Click Me"]', '//a[.="Click Me"]');
$this->assertEquals('//button[@value="Click Me"] | //a[.="Click Me"]', $result);
$result = Locator::combine('button[value="Click Me"]', '//a[.="Click Me"]');
$this->assertEquals('descendant-or-self::button[@value = \'Click Me\'] | //a[.="Click Me"]', $result);
$xml = new SimpleXMLElement("<root><button value='Click Me' /></root>");
$this->assertNotEmpty($xml->xpath($result));
$xml = new SimpleXMLElement("<root><a href='#'>Click Me</a></root>");
$this->assertNotEmpty($xml->xpath($result));
}
public function testHref()
{
$xml = new SimpleXMLElement("<root><a href='/logout'>Click Me</a></root>");
$this->assertNotEmpty($xml->xpath(Locator::href('/logout')));
}
public function testTabIndex()
{
$xml = new SimpleXMLElement("<root><a href='#' tabindex='2'>Click Me</a></root>");
$this->assertNotEmpty($xml->xpath(Locator::tabIndex(2)));
}
public function testFind()
{
$xml = new SimpleXMLElement("<root><a href='#' tabindex='2'>Click Me</a></root>");
$this->assertNotEmpty($xml->xpath(Locator::find('a', array('href' => '#'))));
$this->assertNotEmpty($xml->xpath(Locator::find('a', array('href', 'tabindex' => '2'))));
}
public function testIsXPath()
{
$this->assertTrue(Locator::isXPath("//hr[@class='edge' and position()=1]"));
$this->assertFalse(Locator::isXPath("and position()=1]"));
$this->assertTrue(Locator::isXPath('//table[parent::div[@class="pad"] and not(@id)]//a'));
}
public function testIsId()
{
$this->assertTrue(Locator::isID('#username'));
$this->assertTrue(Locator::isID('#user.name'));
$this->assertTrue(Locator::isID('#user-name'));
$this->assertFalse(Locator::isID('#user-name .field'));
$this->assertFalse(Locator::isID('.field'));
$this->assertFalse(Locator::isID('hello'));
}
public function testIsClass()
{
$this->assertTrue(Locator::isClass('.username'));
$this->assertTrue(Locator::isClass('.name'));
$this->assertTrue(Locator::isClass('.user-name'));
$this->assertFalse(Locator::isClass('.user-name .field'));
$this->assertFalse(Locator::isClass('#field'));
$this->assertFalse(Locator::isClass('hello'));
}
public function testContains()
{
$this->assertEquals(
'descendant-or-self::label[contains(., \'enter a name\')]',
Locator::contains('label', 'enter a name')
);
$this->assertEquals(
'descendant-or-self::label[@id = \'user\'][contains(., \'enter a name\')]',
Locator::contains('label#user', 'enter a name')
);
$this->assertEquals(
'//label[@for="name"][contains(., \'enter a name\')]',
Locator::contains('//label[@for="name"]', 'enter a name')
);
}
public function testHumanReadableString()
{
$this->assertEquals("'string selector'", Locator::humanReadableString("string selector"));
$this->assertEquals("css '.something'", Locator::humanReadableString(['css' => '.something']));
$this->assertEquals(
"css selector '.something'",
Locator::humanReadableString(WebDriverBy::cssSelector('.something'))
);
try {
Locator::humanReadableString(null);
$this->fail("Expected exception when calling humanReadableString() with invalid selector");
} catch (\InvalidArgumentException $e) {
}
}
public function testLocatingElementPosition()
{
$this->assertEquals('(descendant-or-self::p)[position()=1]', Locator::firstElement('p'));
$this->assertEquals('(descendant-or-self::p)[position()=last()]', Locator::lastElement('p'));
$this->assertEquals('(descendant-or-self::p)[position()=1]', Locator::elementAt('p', 1));
$this->assertEquals('(descendant-or-self::p)[position()=last()-0]', Locator::elementAt('p', -1));
$this->assertEquals('(descendant-or-self::p)[position()=last()-1]', Locator::elementAt('p', -2));
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Codeception\Util;
class MockAutoload extends Autoload
{
protected static $files = [];
public static function setFiles(array $files)
{
self::$files = $files;
}
protected static function requireFile($file)
{
return in_array($file, self::$files);
}
}

View File

@@ -0,0 +1,84 @@
<?php
namespace Codeception\Util;
class PathResolverTest extends \Codeception\Test\Unit
{
/**
* @dataProvider getRelativeDirTestData
* @group core
*/
public function testGetRelativeDir($path, $projDir, $dirSep, $expectedOutput)
{
$relativeDir = PathResolver::getRelativeDir($path, $projDir, $dirSep);
$this->assertEquals($expectedOutput, $relativeDir);
}
/**
* data provider for testGetRelativeDir
*
* @return array(array(strings))
*/
public function getRelativeDirTestData()
{
return [
// Unix style paths:
// projectDir() with & without trailing directory seperator: actual subdir
['/my/proj/path/some/file/in/my/proj.txt', '/my/proj/path/', '/', 'some/file/in/my/proj.txt'],
['/my/proj/path/some/file/in/my/proj.txt', '/my/proj/path', '/', 'some/file/in/my/proj.txt'],
['/my/proj/pathsome/file/in/my/proj.txt', '/my/proj/path', '/', '../pathsome/file/in/my/proj.txt'],
// Case sensitive:
['/my/proj/Path/some/file/in/my/proj.txt', '/my/proj/path/', '/', '../Path/some/file/in/my/proj.txt'],
['/my/Proj/path/some/file/in/my/proj.txt', '/my/proj/path', '/', '../../Proj/path/some/file/in/my/proj.txt'],
['My/proj/path/some/file/in/my/proj.txt', 'my/proj/path/foo/bar', '/', '../../../../../My/proj/path/some/file/in/my/proj.txt'],
['/my/proj/path/some/file/in/my/proj.txt', '/my/proj/Path/foobar/', '/', '../../path/some/file/in/my/proj.txt'],
['/my/PROJ/path/some/dir/in/my/proj/', '/my/proj/path/foobar/', '/', '../../../PROJ/path/some/dir/in/my/proj/'],
// Absolute $path, Relative projectDir()
['/my/proj/path/some/file/in/my/proj.txt', 'my/proj/path/', '/', '/my/proj/path/some/file/in/my/proj.txt'],
['/My/proj/path/some/file/in/my/proj.txt', 'my/proj/path/', '/', '/My/proj/path/some/file/in/my/proj.txt'],
// Relative $path, Absolute projectDir()
['my/proj/path/some/file/in/my/proj.txt', '/my/proj/path/', '/', 'my/proj/path/some/file/in/my/proj.txt'],
// $path & projectDir() both relative
['my/proj/path/some/file/in/my/proj.txt', 'my/proj/path/foo/bar', '/', '../../some/file/in/my/proj.txt'],
// $path & projectDir() both absolute: not a subdir
['/my/proj/path/some/file/in/my/proj.txt', '/my/proj/path/foobar/', '/', '../some/file/in/my/proj.txt'],
// ensure trailing DIRECTORY_SEPERATOR maintained
['/my/proj/path/some/dir/in/my/proj/', '/my/proj/path/foobar', '/', '../some/dir/in/my/proj/'],
// Windows style paths:
// projectDir() with & without trailing directory seperator: actual subdir
['C:\\my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'C:\\my\\proj\\path\\', '\\', 'some\\file\\in\\my\\proj.txt'],
['C:\\my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'C:\\my\\proj\\path', '\\', 'some\\file\\in\\my\\proj.txt'],
['C:\\my\\proj\\pathsome\\file\\in\\my\\proj.txt', 'C:\\my\\proj\\path', '\\', '..\\pathsome\\file\\in\\my\\proj.txt'],
// No device letter... absoluteness mismatch
['\\my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'my\\proj\\path\\', '\\', '\\my\\proj\\path\\some\\file\\in\\my\\proj.txt'],
['my\\proj\\path\\some\\file\\in\\my\\proj.txt', '\\my\\proj\\path\\', '\\', 'my\\proj\\path\\some\\file\\in\\my\\proj.txt'],
// No device letter... absoluteness match
['my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'my\\proj\\path\\foo\\bar', '\\', '..\\..\\some\\file\\in\\my\\proj.txt'],
['\\my\\proj\\path\\some\\file\\in\\my\\proj.txt', '\\my\\proj\\path\\foobar\\', '\\', '..\\some\\file\\in\\my\\proj.txt'],
['\\my\\proj\\path\\some\\dir\\in\\my\\proj\\', '\\my\\proj\\path\\foobar\\', '\\', '..\\some\\dir\\in\\my\\proj\\'],
// Device letter (both)... path absoluteness mismatch
['C:\\my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'C:my\\proj\\path\\', '\\', '\\my\\proj\\path\\some\\file\\in\\my\\proj.txt'],
['d:my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'd:\\my\\proj\\path\\', '\\', 'my\\proj\\path\\some\\file\\in\\my\\proj.txt'],
// Device letter (both)... path absoluteness match... case-insensitivity
['E:my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'E:my\\proj\\PATH\\foo\\bar', '\\', '..\\..\\some\\file\\in\\my\\proj.txt'],
['f:\\my\\Proj\\path\\some\\file\\in\\my\\proj.txt', 'F:\\my\\proj\\path\\foobar\\', '\\', '..\\some\\file\\in\\my\\proj.txt'],
['A:\\MY\\proj\\path\\some\\dir\\in\\my\\proj\\', 'a:\\my\\proj\\path\\foobar\\', '\\', '..\\some\\dir\\in\\my\\proj\\'],
// Absoluteness mismatch
['z:\\my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'my\\proj\\path\\', '\\', 'z:\\my\\proj\\path\\some\\file\\in\\my\\proj.txt'],
['Y:my\\proj\\path\\some\\file\\in\\my\\proj.txt', '\\my\\proj\\path\\', '\\', 'Y:my\\proj\\path\\some\\file\\in\\my\\proj.txt'],
['x:my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'my\\proj\\path\\foo\\bar', '\\', 'x:my\\proj\\path\\some\\file\\in\\my\\proj.txt'],
['P:\\my\\proj\\path\\some\\file\\in\\my\\proj.txt', '\\my\\proj\\path\\foobar\\', '\\', 'P:\\my\\proj\\path\\some\\file\\in\\my\\proj.txt'],
['Q:\\my\\proj\\path\\some\\dir\\in\\my\\proj\\', '\\my\\proj\\path\\foobar\\', '\\', 'Q:\\my\\proj\\path\\some\\dir\\in\\my\\proj\\'],
['\\my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'm:my\\proj\\path\\', '\\', '\\my\\proj\\path\\some\\file\\in\\my\\proj.txt'],
['my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'N:\\my\\proj\\path\\', '\\', 'my\\proj\\path\\some\\file\\in\\my\\proj.txt'],
['my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'o:my\\proj\\path\\foo\\bar', '\\', 'my\\proj\\path\\some\\file\\in\\my\\proj.txt'],
['\\my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'P:\\my\\proj\\path\\foobar\\', '\\', '\\my\\proj\\path\\some\\file\\in\\my\\proj.txt'],
['\\my\\proj\\path\\some\\dir\\in\\my\\proj\\', 'q:\\my\\proj\\path\\foobar\\', '\\', '\\my\\proj\\path\\some\\dir\\in\\my\\proj\\'],
// Device letter mismatch
['A:\\my\\proj\\path\\some\\file\\in\\my\\proj.txt', 'B:my\\proj\\path\\', '\\', 'A:\\my\\proj\\path\\some\\file\\in\\my\\proj.txt'],
['c:my\\proj\\path\\some\\file\\in\\my\\proj.json', 'd:\\my\\proj\\path\\', '\\', 'c:my\\proj\\path\\some\\file\\in\\my\\proj.json'],
['M:my\\proj\\path\\foo.txt', 'N:my\\proj\\path\\foo\\bar', '\\', 'M:my\\proj\\path\\foo.txt'],
['G:\\my\\proj\\path\\baz.exe', 'C:\\my\\proj\\path\\foobar\\', '\\', 'G:\\my\\proj\\path\\baz.exe'],
['C:\\my\\proj\\path\\bam\\', 'G:\\my\\proj\\path\\foobar\\', '\\', 'C:\\my\\proj\\path\\bam\\'] ];
}
}

View File

@@ -0,0 +1,447 @@
<?php
use \Codeception\Util\Stub as Stub;
class StubTest extends \PHPUnit\Framework\TestCase
{
/**
* @var DummyClass
*/
protected $dummy;
public function setUp()
{
$conf = \Codeception\Configuration::config();
require_once $file = \Codeception\Configuration::dataDir().'DummyClass.php';
$this->dummy = new DummyClass(true);
}
public function testMakeEmpty()
{
$dummy = Stub::makeEmpty('DummyClass');
$this->assertInstanceOf('DummyClass', $dummy);
$this->assertTrue(method_exists($dummy, 'helloWorld'));
$this->assertNull($dummy->helloWorld());
}
public function testMakeEmptyMethodReplaced()
{
$dummy = Stub::makeEmpty('DummyClass', array('helloWorld' => function () {
return 'good bye world';
}));
$this->assertMethodReplaced($dummy);
}
public function testMakeEmptyMethodSimplyReplaced()
{
$dummy = Stub::makeEmpty('DummyClass', array('helloWorld' => 'good bye world'));
$this->assertMethodReplaced($dummy);
}
public function testMakeEmptyExcept()
{
$dummy = Stub::makeEmptyExcept('DummyClass', 'helloWorld');
$this->assertEquals($this->dummy->helloWorld(), $dummy->helloWorld());
$this->assertNull($dummy->goodByeWorld());
}
public function testMakeEmptyExceptPropertyReplaced()
{
$dummy = Stub::makeEmptyExcept('DummyClass', 'getCheckMe', array('checkMe' => 'checked!'));
$this->assertEquals('checked!', $dummy->getCheckMe());
}
public function testMakeEmptyExceptMagicalPropertyReplaced()
{
$dummy = Stub::makeEmptyExcept('DummyClass', 'getCheckMeToo', array('checkMeToo' => 'checked!'));
$this->assertEquals('checked!', $dummy->getCheckMeToo());
}
public function testFactory()
{
$dummies = Stub::factory('DummyClass', 2);
$this->assertCount(2, $dummies);
$this->assertInstanceOf('DummyClass', $dummies[0]);
}
public function testMake()
{
$dummy = Stub::make('DummyClass', array('goodByeWorld' => function () {
return 'hello world';
}));
$this->assertEquals($this->dummy->helloWorld(), $dummy->helloWorld());
$this->assertEquals("hello world", $dummy->goodByeWorld());
}
public function testMakeMethodReplaced()
{
$dummy = Stub::make('DummyClass', array('helloWorld' => function () {
return 'good bye world';
}));
$this->assertMethodReplaced($dummy);
}
public function testMakeWithMagicalPropertiesReplaced()
{
$dummy = Stub::make('DummyClass', array('checkMeToo' => 'checked!'));
$this->assertEquals('checked!', $dummy->checkMeToo);
}
public function testMakeMethodSimplyReplaced()
{
$dummy = Stub::make('DummyClass', array('helloWorld' => 'good bye world'));
$this->assertMethodReplaced($dummy);
}
public function testCopy()
{
$dummy = Stub::copy($this->dummy, array('checkMe' => 'checked!'));
$this->assertEquals('checked!', $dummy->getCheckMe());
$dummy = Stub::copy($this->dummy, array('checkMeToo' => 'checked!'));
$this->assertEquals('checked!', $dummy->getCheckMeToo());
}
public function testConstruct()
{
$dummy = Stub::construct('DummyClass', array('checkMe' => 'checked!'));
$this->assertEquals('constructed: checked!', $dummy->getCheckMe());
$dummy = Stub::construct(
'DummyClass',
array('checkMe' => 'checked!'),
array('targetMethod' => function () {
return false;
})
);
$this->assertEquals('constructed: checked!', $dummy->getCheckMe());
$this->assertEquals(false, $dummy->targetMethod());
}
public function testConstructMethodReplaced()
{
$dummy = Stub::construct(
'DummyClass',
array(),
array('helloWorld' => function () {
return 'good bye world';
})
);
$this->assertMethodReplaced($dummy);
}
public function testConstructMethodSimplyReplaced()
{
$dummy = Stub::make('DummyClass', array('helloWorld' => 'good bye world'));
$this->assertMethodReplaced($dummy);
}
public function testConstructEmpty()
{
$dummy = Stub::constructEmpty('DummyClass', array('checkMe' => 'checked!'));
$this->assertNull($dummy->getCheckMe());
}
public function testConstructEmptyExcept()
{
$dummy = Stub::constructEmptyExcept('DummyClass', 'getCheckMe', array('checkMe' => 'checked!'));
$this->assertNull($dummy->targetMethod());
$this->assertEquals('constructed: checked!', $dummy->getCheckMe());
}
public function testUpdate()
{
$dummy = Stub::construct('DummyClass');
Stub::update($dummy, array('checkMe' => 'done'));
$this->assertEquals('done', $dummy->getCheckMe());
Stub::update($dummy, array('checkMeToo' => 'done'));
$this->assertEquals('done', $dummy->getCheckMeToo());
}
public function testStubsFromObject()
{
$dummy = Stub::make(new \DummyClass());
$this->assertInstanceOf(
'\PHPUnit_Framework_MockObject_MockObject',
$dummy
);
$dummy = Stub::make(new \DummyOverloadableClass());
$this->assertObjectHasAttribute('__mocked', $dummy);
$dummy = Stub::makeEmpty(new \DummyClass());
$this->assertInstanceOf(
'\PHPUnit_Framework_MockObject_MockObject',
$dummy
);
$dummy = Stub::makeEmpty(new \DummyOverloadableClass());
$this->assertObjectHasAttribute('__mocked', $dummy);
$dummy = Stub::makeEmptyExcept(new \DummyClass(), 'helloWorld');
$this->assertInstanceOf(
'\PHPUnit_Framework_MockObject_MockObject',
$dummy
);
$dummy = Stub::makeEmptyExcept(new \DummyOverloadableClass(), 'helloWorld');
$this->assertObjectHasAttribute('__mocked', $dummy);
$dummy = Stub::construct(new \DummyClass());
$this->assertInstanceOf(
'\PHPUnit_Framework_MockObject_MockObject',
$dummy
);
$dummy = Stub::construct(new \DummyOverloadableClass());
$this->assertObjectHasAttribute('__mocked', $dummy);
$dummy = Stub::constructEmpty(new \DummyClass());
$this->assertInstanceOf(
'\PHPUnit_Framework_MockObject_MockObject',
$dummy
);
$dummy = Stub::constructEmpty(new \DummyOverloadableClass());
$this->assertObjectHasAttribute('__mocked', $dummy);
$dummy = Stub::constructEmptyExcept(new \DummyClass(), 'helloWorld');
$this->assertInstanceOf(
'\PHPUnit_Framework_MockObject_MockObject',
$dummy
);
$dummy = Stub::constructEmptyExcept(new \DummyOverloadableClass(), 'helloWorld');
$this->assertObjectHasAttribute('__mocked', $dummy);
}
protected function assertMethodReplaced($dummy)
{
$this->assertTrue(method_exists($dummy, 'helloWorld'));
$this->assertNotEquals($this->dummy->helloWorld(), $dummy->helloWorld());
$this->assertEquals($dummy->helloWorld(), 'good bye world');
}
public static function matcherAndFailMessageProvider()
{
return array(
array(Stub::never(),
"DummyClass::targetMethod() was not expected to be called."
),
array(Stub::atLeastOnce(),
"Expectation failed for method name is equal to <string:targetMethod> when invoked at least once.\n"
. 'Expected invocation at least once but it never occured.'
),
array(Stub::once(),
"Expectation failed for method name is equal to <string:targetMethod> when invoked 1 time(s).\n"
. 'Method was expected to be called 1 times, actually called 0 times.'
),
array(Stub::exactly(1),
"Expectation failed for method name is equal to <string:targetMethod> when invoked 3 time(s).\n"
. 'Method was expected to be called 3 times, actually called 0 times.'
),
array(Stub::exactly(3),
"Expectation failed for method name is equal to <string:targetMethod> when invoked 3 time(s).\n"
. 'Method was expected to be called 3 times, actually called 0 times.'
),
);
}
/**
* @dataProvider matcherAndFailMessageProvider
*/
public function testMockedMethodIsCalledFail($stubMarshaler, $failMessage)
{
$mock = Stub::makeEmptyExcept('DummyClass', 'call', array('targetMethod' => $stubMarshaler), $this);
$mock->goodByeWorld();
try {
if ($this->thereAreNeverMatcher($stubMarshaler)) {
$this->thenWeMustCallMethodForException($mock);
} else {
$this->thenWeDontCallAnyMethodForExceptionJustVerify($mock);
}
} catch (PHPUnit\Framework\ExpectationFailedException $e) {
$this->assertSame($failMessage, $e->getMessage());
}
$this->resetMockObjects();
}
private function thenWeMustCallMethodForException($mock)
{
$mock->call();
}
private function thenWeDontCallAnyMethodForExceptionJustVerify($mock)
{
$mock->__phpunit_verify();
$this->fail('Expected exception');
}
private function thereAreNeverMatcher($stubMarshaler)
{
$matcher = $stubMarshaler->getMatcher();
return 0 == $matcher->getInvocationCount();
}
private function resetMockObjects()
{
$refl = new ReflectionObject($this);
$refl = $refl->getParentClass();
$prop = $refl->getProperty('mockObjects');
$prop->setAccessible(true);
$prop->setValue($this, array());
}
public static function matcherProvider()
{
return array(
array(0, Stub::never()),
array(1, Stub::once()),
array(2, Stub::atLeastOnce()),
array(3, Stub::exactly(3)),
array(1, Stub::once(function () {
return true;
}), true),
array(2, Stub::atLeastOnce(function () {
return array();
}), array()),
array(1, Stub::exactly(1, function () {
return null;
}), null),
array(1, Stub::exactly(1, function () {
return 'hello world!';
}), 'hello world!'),
);
}
/**
* @dataProvider matcherProvider
*/
public function testMethodMatcherWithMake($count, $matcher, $expected = false)
{
$dummy = Stub::make('DummyClass', array('goodByeWorld' => $matcher), $this);
$this->repeatCall($count, array($dummy, 'goodByeWorld'), $expected);
}
/**
* @dataProvider matcherProvider
*/
public function testMethodMatcherWithMakeEmpty($count, $matcher)
{
$dummy = Stub::makeEmpty('DummyClass', array('goodByeWorld' => $matcher), $this);
$this->repeatCall($count, array($dummy, 'goodByeWorld'));
}
/**
* @dataProvider matcherProvider
*/
public function testMethodMatcherWithMakeEmptyExcept($count, $matcher)
{
$dummy = Stub::makeEmptyExcept('DummyClass', 'getCheckMe', array('goodByeWorld' => $matcher), $this);
$this->repeatCall($count, array($dummy, 'goodByeWorld'));
}
/**
* @dataProvider matcherProvider
*/
public function testMethodMatcherWithConstruct($count, $matcher)
{
$dummy = Stub::construct('DummyClass', array(), array('goodByeWorld' => $matcher), $this);
$this->repeatCall($count, array($dummy, 'goodByeWorld'));
}
/**
* @dataProvider matcherProvider
*/
public function testMethodMatcherWithConstructEmpty($count, $matcher)
{
$dummy = Stub::constructEmpty('DummyClass', array(), array('goodByeWorld' => $matcher), $this);
$this->repeatCall($count, array($dummy, 'goodByeWorld'));
}
/**
* @dataProvider matcherProvider
*/
public function testMethodMatcherWithConstructEmptyExcept($count, $matcher)
{
$dummy = Stub::constructEmptyExcept(
'DummyClass',
'getCheckMe',
array(),
array('goodByeWorld' => $matcher),
$this
);
$this->repeatCall($count, array($dummy, 'goodByeWorld'));
}
private function repeatCall($count, $callable, $expected = false)
{
for ($i = 0; $i < $count; $i++) {
$actual = call_user_func($callable);
if ($expected) {
$this->assertEquals($expected, $actual);
}
}
}
public function testConsecutive()
{
$dummy = Stub::make('DummyClass', array('helloWorld' => Stub::consecutive('david', 'emma', 'sam', 'amy')));
$this->assertEquals('david', $dummy->helloWorld());
$this->assertEquals('emma', $dummy->helloWorld());
$this->assertEquals('sam', $dummy->helloWorld());
$this->assertEquals('amy', $dummy->helloWorld());
// Expected null value when no more values
$this->assertNull($dummy->helloWorld());
}
public function testStubPrivateProperties()
{
$tester = Stub::construct(
'MyClassWithPrivateProperties',
['name' => 'gamma'],
[
'randomName' => 'chicken',
't' => 'ticky2',
'getRandomName' => function () {
return "randomstuff";
}
]
);
$this->assertEquals('gamma', $tester->getName());
$this->assertEquals('randomstuff', $tester->getRandomName());
$this->assertEquals('ticky2', $tester->getT());
}
public function testStubMakeEmptyInterface()
{
$stub = Stub::makeEmpty('\Countable', ['count' => 5]);
$this->assertEquals(5, $stub->count());
}
}
class MyClassWithPrivateProperties
{
private $name;
private $randomName = "gaia";
private $t = "ticky";
public function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
public function getRandomName()
{
return $this->randomName;
}
public function getT()
{
return $this->t;
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Codeception\Util;
class TemplateTest extends \PHPUnit\Framework\TestCase
{
public function testTemplateCanPassValues()
{
$template = new Template("hello, {{name}}");
$template->place('name', 'davert');
$this->assertEquals('hello, davert', $template->produce());
}
public function testTemplateCanHaveOtherPlaceholder()
{
$template = new Template("hello, %name%", '%', '%');
$template->place('name', 'davert');
$this->assertEquals('hello, davert', $template->produce());
}
public function testTemplateSupportsDotNotationForArrays()
{
$template = new Template("hello, {{user.data.name}}");
$template->place('user', ['data' => ['name' => 'davert']]);
$this->assertEquals('hello, davert', $template->produce());
}
public function testShouldSkipUnmatchedPlaceholder()
{
$template = new Template("hello, {{name}}");
$this->assertEquals('hello, {{name}}', $template->produce());
}
}

View File

@@ -0,0 +1,122 @@
<?php
namespace Codeception\Util;
class UriTest extends \Codeception\Test\Unit
{
// tests
public function testUrlMerge()
{
$this->assertEquals(
'http://codeception.com/quickstart',
Uri::mergeUrls('http://codeception.com/hello', '/quickstart'),
'merge paths'
);
$this->assertEquals(
'http://codeception.com/hello/davert',
Uri::mergeUrls('http://codeception.com/hello/world', 'davert'),
'merge relative urls'
);
$this->assertEquals(
'https://github.com/codeception/codeception',
Uri::mergeUrls('http://codeception.com/hello/world', 'https://github.com/codeception/codeception'),
'merge absolute urls'
);
}
/**
* @Issue https://github.com/Codeception/Codeception/pull/2141
*/
public function testMergingScheme()
{
$this->assertEquals(
'https://google.com/account/',
Uri::mergeUrls('http://google.com/', 'https://google.com/account/')
);
$this->assertEquals('https://facebook.com/', Uri::mergeUrls('https://google.com/test/', '//facebook.com/'));
$this->assertEquals(
'https://facebook.com/#anchor2',
Uri::mergeUrls('https://google.com/?param=1#anchor', '//facebook.com/#anchor2')
);
}
/**
* @Issue https://github.com/Codeception/Codeception/pull/2841
*/
public function testMergingPath()
{
$this->assertEquals('/form/?param=1#anchor', Uri::mergeUrls('/form/?param=1', '#anchor'));
$this->assertEquals('/form/?param=1#anchor2', Uri::mergeUrls('/form/?param=1#anchor1', '#anchor2'));
$this->assertEquals('/form/?param=2', Uri::mergeUrls('/form/?param=1#anchor', '?param=2'));
$this->assertEquals('/page/', Uri::mergeUrls('/form/?param=1#anchor', '/page/'));
}
/**
* @Issue https://github.com/Codeception/Codeception/pull/4847
*/
public function testMergingNonParsingPath()
{
$this->assertEquals('/3.0/en/index/page:5', Uri::mergeUrls('https://cakephp.org/', '/3.0/en/index/page:5'));
}
/**
* @Issue https://github.com/Codeception/Codeception/pull/2499
*/
public function testAppendAnchor()
{
$this->assertEquals(
'http://codeception.com/quickstart#anchor',
Uri::appendPath('http://codeception.com/quickstart', '#anchor')
);
$this->assertEquals(
'http://codeception.com/quickstart#anchor',
Uri::appendPath('http://codeception.com/quickstart#first', '#anchor')
);
}
public function testAppendPath()
{
$this->assertEquals(
'http://codeception.com/quickstart/path',
Uri::appendPath('http://codeception.com/quickstart', 'path')
);
$this->assertEquals(
'http://codeception.com/quickstart/path',
Uri::appendPath('http://codeception.com/quickstart', '/path')
);
}
public function testAppendEmptyPath()
{
$this->assertEquals(
'http://codeception.com/quickstart',
Uri::appendPath('http://codeception.com/quickstart', '')
);
}
public function testAppendPathRemovesQueryStringAndAnchor()
{
$this->assertEquals(
'http://codeception.com/quickstart',
Uri::appendPath('http://codeception.com/quickstart?a=b#c', '')
);
}
public function testMergeUrlsWhenBaseUriHasNoTrailingSlashAndUriPathHasNoLeadingSlash()
{
$this->assertEquals(
'http://codeception.com/test',
Uri::mergeUrls('http://codeception.com', 'test'));
}
public function testMergeUrlsWhenBaseUriEndsWithSlashButUriPathHasNoLeadingSlash()
{
$this->assertEquals(
'http://codeception.com/test',
Uri::mergeUrls('http://codeception.com/', 'test'));
}
}