Laravel version update

Laravel version update
This commit is contained in:
Manish Verma
2018-08-06 18:48:58 +05:30
parent d143048413
commit 126fbb0255
13678 changed files with 1031482 additions and 778530 deletions

View File

@@ -17,13 +17,14 @@ matrix:
env: DEPENDENCIES='dev'
- php: 5.6
- php: hhvm
dist: trusty
- php: 7.0
allow_failures:
- env: DEPENDENCIES='dev'
fast_finish: true
before_install:
- if [[ ${TRAVIS_PHP_VERSION:0:4} != "hhvm" ]]; then phpenv config-rm xdebug.ini; fi
- phpenv config-rm xdebug.ini || true
install:
- export COMPOSER_ROOT_VERSION=dev-master
@@ -32,6 +33,24 @@ install:
- if [ "$DEPENDENCIES" == "low" ]; then composer update --prefer-lowest; fi;
script:
- bin/phpspec run --format=pretty
- ./vendor/bin/phpunit --testdox
- ./vendor/bin/behat --format=pretty
- bin/phpspec run --format=dot
- ./vendor/bin/phpunit
- ./vendor/bin/behat --format=progress
before_deploy:
- curl -LSs https://box-project.github.io/box2/installer.php | php
- export PATH=.:$PATH
- rm -Rf ./vendor
- composer install --no-dev -o
- box.phar build
deploy:
provider: releases
api_key:
secure: eTlXM76IvH1Ws57gtBi5Q7trQ3rEXjt+7wOH4HLw6WhhywMF4THMuQQC0j5DhWtiLJlVYHaIfNbapbG+DVUqyXZZA+aXQSuh9aNM1fbkEShbWFpOrCd+Y3I1lXNvOcGZ5hvJieDVgWSc0osNLCQzaza17fhYUtbKsj4Qwc5ek8k=
file: phpspec.phar
skip_cleanup: true
on:
tags: true
php: 5.6
condition: $DEPENDENCIES != "low"

View File

@@ -1,3 +1,30 @@
2.5.8 / 2017-07-29
==================
* [fixed] parameters after extensions ignored in config file (@borNfreee)
2.5.7 / 2017-05-12
==================
* [fixed] constructor no longer generated multuple tiles (@CarlosV2)
* [fixed] warning when src_path is empty (@vitorf7)
2.5.6 / 2017-04-27
==================
* Support sebastian/exporter 2.0 and 3.0 (@mattsches and @remicollet)
2.5.5 / 2016-12-04
==================
* [fixed] PHP 5.3 support was broken (@unfunco)
2.5.4 / 2016-12-02
==================
* [fixed] Prevent deprecation warning in Symfony 3.2.0 (@veewee)
* [performance] Reduced size of Phar (@unfunco)
2.5.3 / 2016-09-26
==================

View File

@@ -1,13 +0,0 @@
all:
@echo "Only build-phar target is currently supported."
build-phar:
@echo "--> Checking for composer command line tool"
command -v composer >/dev/null && continue || { echo "composer command not found."; exit 1; }
@echo "--> Cleaning vendor directory"
rm -Rfv vendor
@echo "--> Installing dependencies without dev"
composer install --no-dev -o
@echo "--> Building Phar"
box build
@echo "--> Success"

View File

@@ -41,6 +41,6 @@ install:
test_script:
- cd c:\projects\phpspec
- php bin\phpspec run --format=pretty
- php vendor\phpunit\phpunit\phpunit --testdox
- php vendor\behat\behat\bin\behat --format=pretty --tags="~@php-version,@php5.4&&~@hhvm"
- php bin\phpspec run --format=dot
- php vendor\phpunit\phpunit\phpunit
- php vendor\behat\behat\bin\behat --format=progress --tags="~@php-version,@php5.4&&~@hhvm"

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env php
<?php
define('PHPSPEC_VERSION', '2.5.3');
define('PHPSPEC_VERSION', '2.5.8');
if (is_file($autoload = getcwd() . '/vendor/autoload.php')) {
require $autoload;

View File

@@ -9,7 +9,7 @@
"finder": [
{
"name": "*.php",
"exclude": ["Tests"],
"exclude": ["spec", "Tests", "tests"],
"in": "vendor"
}
],

View File

@@ -21,8 +21,8 @@
"php": ">=5.3.3",
"phpspec/prophecy": "~1.4",
"phpspec/php-diff": "~1.0.0",
"sebastian/exporter": "~1.0",
"symfony/console": "~2.3|~3.0",
"sebastian/exporter": "~1.0|~2.0|^3.0",
"symfony/console": "~2.3|~3.0,!=3.2.8",
"symfony/event-dispatcher": "~2.1|~3.0",
"symfony/process": "^2.6|~3.0",
"symfony/finder": "~2.1|~3.0",
@@ -32,7 +32,7 @@
},
"require-dev": {
"behat/behat": "^3.0.11",
"behat/behat": "^3.0.11,!=3.3.1",
"symfony/filesystem": "~2.1|~3.0",
"phpunit/phpunit": "~4.4",
"ciaranmcnulty/versionbasedtestskipper": "^0.2.1"

View File

@@ -118,6 +118,24 @@ class ApplicationContext implements Context
* @When I run phpspec with the option :option and (I) answer :answer when asked if I want to generate the code
*/
public function iRunPhpspecAndAnswerWhenAskedIfIWantToGenerateTheCode($answer, $option=null)
{
$this->runPhpSpecAndAnswerQuestions($answer, 1, $option);
}
/**
* @When I run phpspec and answer :answer to (the) :amount questions
*/
public function iRunPhpspecAndAnswerToBothQuestions($amount, $answer)
{
$this->runPhpSpecAndAnswerQuestions($answer, ($amount === 'both' ? 2 : 3));
}
/**
* @param string $answer
* @param integer $times
* @param string $option
*/
private function runPhpSpecAndAnswerQuestions($answer, $times, $option = null)
{
$arguments = array (
'command' => 'run'
@@ -125,22 +143,10 @@ class ApplicationContext implements Context
$this->addOptionToArguments($option, $arguments);
$this->prompter->setAnswer($answer=='y');
$this->lastExitCode = $this->tester->run($arguments, array('interactive' => true));
}
/**
* @When I run phpspec and answer :answer to both questions
*/
public function iRunPhpspecAndAnswerToBothQuestions($answer)
{
$arguments = array (
'command' => 'run'
);
$this->prompter->setAnswer($answer=='y');
$this->prompter->setAnswer($answer=='y');
$i = 0;
while ($i++ < $times) {
$this->prompter->setAnswer($answer=='y');
}
$this->lastExitCode = $this->tester->run($arguments, array('interactive' => true));
}
@@ -360,4 +366,16 @@ class ApplicationContext implements Context
return $string;
}
/**
* @Then I should not be prompted for more questions
*/
public function iShouldNotBePromptedForMoreQuestions()
{
if ($this->prompter->hasUnansweredQuestions()) {
throw new \Exception(
'Not all questions were answered. This might lead into further code generation not reflected in the scenario.'
);
}
}
}

View File

@@ -9,6 +9,7 @@ class Prompter implements PrompterInterface
private $answers = array();
private $hasBeenAsked = false;
private $question;
private $unansweredQuestions = false;
public function setAnswer($answer)
{
@@ -19,6 +20,8 @@ class Prompter implements PrompterInterface
{
$this->hasBeenAsked = true;
$this->question = $question;
$this->unansweredQuestions = count($this->answers) > 1;
return (bool)array_shift($this->answers);
}
@@ -29,6 +32,19 @@ class Prompter implements PrompterInterface
}
return $this->hasBeenAsked
&& preg_replace('/\s+/', ' ', trim(strip_tags($this->question))) == preg_replace('/\s+/', ' ', $question) ;
&& $this->normalise($this->question) == $this->normalise($question);
}
public function hasUnansweredQuestions()
{
return $this->unansweredQuestions;
}
/**
* @return mixed
*/
private function normalise($question)
{
return preg_replace('/\s+/', '', trim(strip_tags($question)));
}
}

View File

@@ -442,3 +442,75 @@ Feature: Developer generates a named constructor
}
"""
Scenario: Generating multiple named constructors at once
Given the spec file "spec/CodeGeneration/PrivateConstructor/AgeSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\PrivateConstructor;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class AgeSpec extends ObjectBehavior
{
function it_is_constructed_from_string()
{
$this->beConstructedFromString('30');
$this->getAge()->shouldReturn(30);
}
function it_is_constructed_from_integer()
{
$this->beConstructedFromInteger(30);
$this->getAge()->shouldReturn(30);
}
}
"""
And the class file "src/CodeGeneration/PrivateConstructor/Age.php" contains:
"""
<?php
namespace CodeGeneration\PrivateConstructor;
class Age
{
}
"""
When I run phpspec and answer "y" to the three questions
Then I should not be prompted for more questions
And the class in "src/CodeGeneration/PrivateConstructor/Age.php" should contain:
"""
<?php
namespace CodeGeneration\PrivateConstructor;
class Age
{
private function __construct()
{
}
public static function fromInteger($argument1)
{
$age = new Age();
// TODO: write logic here
return $age;
}
public static function fromString($argument1)
{
$age = new Age();
// TODO: write logic here
return $age;
}
}
"""

View File

@@ -0,0 +1,61 @@
Feature: Developer uses bootstrap config key in any place
As a Developer
I want to place configuration options at any part of the config file
Scenario: Extension does not break container parameters
Given the config file contains:
"""
extensions:
- Example1\PhpSpec\LoadsConsoleIoExtension\Extension
bootstrap: NotExisting.php
"""
And the class file "src/Example1/PhpSpec/LoadsConsoleIoExtension/Extension.php" contains:
"""
<?php
namespace Example1\PhpSpec\LoadsConsoleIoExtension;
use PhpSpec\Extension\ExtensionInterface as PhpSpecExtension;
use PhpSpec\ServiceContainer;
class Extension implements PhpSpecExtension
{
public function load(ServiceContainer $container)
{
$container->get('console.io');
}
}
"""
And the spec file "spec/Example1/TestConfigSpec.php" contains:
"""
<?php
namespace spec\Example1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class TestConfigSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('Example1\TestConfig');
}
}
"""
And the class file "src/Example1/TestConfig.php" contains:
"""
<?php
namespace Example1;
class TestConfig
{
}
"""
When I run phpspec
Then I should see "Bootstrap file 'NotExisting.php' does not exist"

View File

@@ -0,0 +1,57 @@
<?php
namespace spec\PhpSpec\CodeGenerator\Generator;
use PhpSpec\CodeGenerator\Generator\GeneratorInterface;
use PhpSpec\Console\IO;
use PhpSpec\ObjectBehavior;
use PhpSpec\Locator\ResourceInterface;
class ConfirmingGeneratorSpec extends ObjectBehavior
{
function let(IO $io, GeneratorInterface $generator)
{
$this->beConstructedWith($io, 'Question for {CLASSNAME}', $generator);
}
function it_is_a_Generator()
{
$this->shouldHaveType('PhpSpec\CodeGenerator\Generator\GeneratorInterface');
}
function it_supports_the_same_generator_as_its_parent(GeneratorInterface $generator, ResourceInterface $resource)
{
$generator->supports($resource, 'generation', array())->willReturn(true);
$this->supports($resource, 'generation', array())->shouldReturn(true);
}
function it_has_the_same_priority_as_its_parent(GeneratorInterface $generator)
{
$generator->getPriority()->willReturn(1324);
$this->getPriority()->shouldReturn(1324);
}
function it_does_not_call_the_parent_generate_method_if_the_user_answers_no(GeneratorInterface $generator, ResourceInterface $resource, IO $io)
{
$resource->getSrcClassname()->willReturn('Namespace/Classname');
$io->askConfirmation('Question for Namespace/Classname')->willReturn(false);
$this->generate($resource, array());
$generator->generate($resource, array())->shouldNotHaveBeenCalled();
}
function it_calls_the_parent_generate_method_if_the_user_answers_yes(GeneratorInterface $generator, ResourceInterface $resource, IO $io)
{
$resource->getSrcClassname()->willReturn('Namespace/Classname');
$io->askConfirmation('Question for Namespace/Classname')->willReturn(true);
$this->generate($resource, array());
$generator->generate($resource, array())->shouldHaveBeenCalled();
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace spec\PhpSpec\CodeGenerator\Generator;
use PhpSpec\CodeGenerator\Generator\GeneratorInterface;
use PhpSpec\ObjectBehavior;
use PhpSpec\Locator\ResourceInterface;
class OneTimeGeneratorSpec extends ObjectBehavior
{
function let(GeneratorInterface $generator)
{
$this->beConstructedWith($generator);
}
function it_is_a_Generator()
{
$this->shouldHaveType('PhpSpec\CodeGenerator\Generator\GeneratorInterface');
}
function it_supports_the_same_generator_as_its_parent(GeneratorInterface $generator, ResourceInterface $resource)
{
$generator->supports($resource, 'generation', array())->willReturn(true);
$this->supports($resource, 'generation', array())->shouldReturn(true);
}
function it_has_the_same_priority_as_its_parent(GeneratorInterface $generator)
{
$generator->getPriority()->willReturn(1324);
$this->getPriority()->shouldReturn(1324);
}
function it_calls_the_parent_generate_method_just_once_for_the_same_classname(GeneratorInterface $generator, ResourceInterface $resource)
{
$resource->getSrcClassname()->willReturn('Namespace/Classname');
$this->generate($resource, array());
$this->generate($resource, array());
$generator->generate($resource, array())->shouldHaveBeenCalledTimes(1);
}
function it_calls_the_parent_generate_method_once_per_each_classname(GeneratorInterface $generator, ResourceInterface $resource)
{
$resource->getSrcClassname()->willReturn('Namespace/Classname1', 'Namespace/Classname2');
$this->generate($resource, array());
$this->generate($resource, array());
$generator->generate($resource, array())->shouldHaveBeenCalledTimes(2);
}
}

View File

@@ -0,0 +1,83 @@
<?php
/*
* This file is part of PhpSpec, A php toolset to drive emergent
* design by specification.
*
* (c) Marcello Duarte <marcello.duarte@gmail.com>
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PhpSpec\CodeGenerator\Generator;
use PhpSpec\Console\IO;
use PhpSpec\Locator\ResourceInterface;
final class ConfirmingGenerator implements GeneratorInterface
{
/**
* @var IO
*/
private $io;
/**
* @var string
*/
private $message;
/**
* @var GeneratorInterface
*/
private $generator;
/**
* @param IO $io
* @param string $message
* @param GeneratorInterface $generator
*/
public function __construct(IO $io, $message, GeneratorInterface $generator)
{
$this->io = $io;
$this->message = $message;
$this->generator = $generator;
}
/**
* {@inheritdoc}
*/
public function supports(ResourceInterface $resource, $generation, array $data)
{
return $this->generator->supports($resource, $generation, $data);
}
/**
* {@inheritdoc}
*/
public function generate(ResourceInterface $resource, array $data)
{
if ($this->io->askConfirmation($this->composeMessage($resource))) {
$this->generator->generate($resource, $data);
}
}
/**
* @param ResourceInterface $resource
*
* @return string
*/
private function composeMessage(ResourceInterface $resource)
{
return str_replace('{CLASSNAME}', $resource->getSrcClassname(), $this->message);
}
/**
* {@inheritdoc}
*/
public function getPriority()
{
return $this->generator->getPriority();
}
}

View File

@@ -0,0 +1,67 @@
<?php
/*
* This file is part of PhpSpec, A php toolset to drive emergent
* design by specification.
*
* (c) Marcello Duarte <marcello.duarte@gmail.com>
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PhpSpec\CodeGenerator\Generator;
use PhpSpec\Locator\ResourceInterface;
final class OneTimeGenerator implements GeneratorInterface
{
/**
* @var GeneratorInterface
*/
private $generator;
/**
* @var array
*/
private $alreadyGenerated = array();
/**
* @param GeneratorInterface $generator
*/
public function __construct(GeneratorInterface $generator)
{
$this->generator = $generator;
}
/**
* {@inheritdoc}
*/
public function supports(ResourceInterface $resource, $generation, array $data)
{
return $this->generator->supports($resource, $generation, $data);
}
/**
* {@inheritdoc}
*/
public function generate(ResourceInterface $resource, array $data)
{
$classname = $resource->getSrcClassname();
if (in_array($classname, $this->alreadyGenerated)) {
return;
}
$this->generator->generate($resource, $data);
$this->alreadyGenerated[] = $classname;
}
/**
* {@inheritdoc}
*/
public function getPriority()
{
return $this->generator->getPriority();
}
}

View File

@@ -86,7 +86,14 @@ class Application extends BaseApplication
$this->setDispatcher($this->container->get('console_event_dispatcher'));
$this->container->get('console.io')->setConsoleWidth($this->getTerminalWidth());
if (class_exists('\Symfony\Component\Console\Terminal')) {
$terminal = new \Symfony\Component\Console\Terminal();
$consoleWidth = $terminal->getWidth();
} else {
$consoleWidth = $this->getTerminalWidth();
}
$this->container->get('console.io')->setConsoleWidth($consoleWidth);
StreamWrapper::reset();
foreach ($this->container->getByPrefix('loader.resource_loader.spec_transformer') as $transformer) {
@@ -140,6 +147,8 @@ class Application extends BaseApplication
{
$config = $this->parseConfigurationFile($input);
$this->populateContainerParameters($container, $config);
foreach ($config as $key => $val) {
if ('extensions' === $key && is_array($val)) {
foreach ($val as $class) {
@@ -154,7 +163,14 @@ class Application extends BaseApplication
$extension->load($container);
}
} else {
}
}
}
private function populateContainerParameters(ServiceContainer $container, array $config)
{
foreach ($config as $key => $val) {
if ('extensions' !== $key) {
$container->setParam($key, $val);
}
}

View File

@@ -45,6 +45,7 @@ class ContainerAssembler
*/
public function build(ServiceContainer $container)
{
$this->setupParameters($container);
$this->setupIO($container);
$this->setupEventDispatcher($container);
$this->setupConsoleEventDispatcher($container);
@@ -63,6 +64,14 @@ class ContainerAssembler
$this->setupShutdown($container);
}
private function setupParameters(ServiceContainer $container)
{
$container->setParam(
'generator.private-constructor.message',
'Do you want me to make the constructor of {CLASSNAME} private for you?'
);
}
private function setupIO(ServiceContainer $container)
{
if (!$container->isDefined('console.prompter')) {
@@ -292,9 +301,15 @@ class ContainerAssembler
});
$container->set('code_generator.generators.private_constructor', function (ServiceContainer $c) {
return new CodeGenerator\Generator\PrivateConstructorGenerator(
$c->get('console.io'),
$c->get('code_generator.templates')
return new CodeGenerator\Generator\OneTimeGenerator(
new CodeGenerator\Generator\ConfirmingGenerator(
$c->get('console.io'),
$c->getParam('generator.private-constructor.message'),
new CodeGenerator\Generator\PrivateConstructorGenerator(
$c->get('console.io'),
$c->get('code_generator.templates')
)
)
);
});
@@ -357,7 +372,7 @@ class ContainerAssembler
$config = array_merge($defaults, $suite);
if (!is_dir($config['src_path'])) {
if (!empty($config['src_path']) && !is_dir($config['src_path'])) {
mkdir($config['src_path'], 0777, true);
}
if (!is_dir($config['spec_path'])) {

View File

@@ -47,7 +47,7 @@ class Formatter extends OutputFormatter
$this->setStyle('passed-bg', new OutputFormatterStyle('black', 'green', array('bold')));
$this->setStyle('value', new OutputFormatterStyle('yellow'));
$this->setStyle('lineno', new OutputFormatterStyle(null, 'black'));
$this->setStyle('lineno', new OutputFormatterStyle(null));
$this->setStyle('code', new OutputFormatterStyle('white'));
$this->setStyle('label', new OutputFormatterStyle('white', null, array('bold')));
$this->setStyle('hl', new OutputFormatterStyle('black', 'yellow', array('bold')));

View File

@@ -81,14 +81,10 @@ class NamedConstructorNotFoundListener implements EventSubscriberInterface
$event->markAsWorthRerunning();
if (!method_exists($classname, '__construct')) {
$message = sprintf('Do you want me to make the constructor of %s private for you?', $classname);
if ($this->io->askConfirmation($message)) {
$this->generator->generate($resource, 'private-constructor', array(
'name' => $method,
'arguments' => $arguments
));
}
$this->generator->generate($resource, 'private-constructor', array(
'name' => $method,
'arguments' => $arguments
));
}
}
}

View File

@@ -1,4 +0,0 @@
*.tgz
*.phar
/composer.lock
/vendor

View File

@@ -1,29 +0,0 @@
language: php
php: [5.3, 5.4, 5.5, 5.6, 7.0, hhvm]
sudo: false
cache:
directories:
- $HOME/.composer/cache
branches:
except:
- /^bugfix\/.*$/
- /^feature\/.*$/
- /^optimization\/.*$/
matrix:
fast_finish: true
include:
- php: '7.0'
env: PHPDOCUMENTOR_REFLECTION_DOCBLOCK="^2.0"
before_script:
- if [ -n "$PHPDOCUMENTOR_REFLECTION_DOCBLOCK" ]; then
composer require "phpdocumentor/reflection-docblock:${PHPDOCUMENTOR_REFLECTION_DOCBLOCK}" --no-update;
fi;
- travis_retry composer update --no-interaction
script: vendor/bin/phpspec run -fpretty -v

View File

@@ -1,3 +1,69 @@
1.8.0 / 2018/08/05
==================
* Support for void return types without explicit will (@crellbar)
* Clearer error message for unexpected method calls (@meridius)
* Clearer error message for aggregate exceptions (@meridius)
* More verbose `shouldBeCalledOnce` expectation (@olvlvl)
* Ability to double Throwable, or methods that extend it (@ciaranmcnulty)
* [fixed] Doubling methods where class has additional arguments to interface (@webimpress)
* [fixed] Doubling methods where arguments are nullable but default is not null (@webimpress)
* [fixed] Doubling magic methods on parent class (@dsnopek)
* [fixed] Check method predictions only once (@dontub)
* [fixed] Argument::containingString throwing error when called with non-string (@dcabrejas)
1.7.6 / 2018/04/18
==================
* Allow sebastian/comparator ^3.0 (@sebastianbergmann)
1.7.5 / 2018/02/11
==================
* Support for object return type hints (thanks @greg0ire)
1.7.4 / 2018/02/11
==================
* Fix issues with PHP 7.2 (thanks @greg0ire)
* Support object type hints in PHP 7.2 (thanks @@jansvoboda11)
1.7.3 / 2017/11/24
==================
* Fix SplInfo ClassPatch to work with Symfony 4 (Thanks @gnugat)
1.7.2 / 2017-10-04
==================
* Reverted "check method predictions only once" due to it breaking Spies
1.7.1 / 2017-10-03
==================
* Allow PHP5 keywords methods generation on PHP7 (thanks @bycosta)
* Allow reflection-docblock v4 (thanks @GrahamCampbell)
* Check method predictions only once (thanks @dontub)
* Escape file path sent to \SplFileObjectConstructor when running on Windows (thanks @danmartin-epiphany)
1.7.0 / 2017-03-02
==================
* Add full PHP 7.1 Support (thanks @prolic)
* Allow `sebastian/comparator ^2.0` (thanks @sebastianbergmann)
* Allow `sebastian/recursion-context ^3.0` (thanks @sebastianbergmann)
* Allow `\Error` instances in `ThrowPromise` (thanks @jameshalsall)
* Support `phpspec/phpspect ^3.2` (thanks @Sam-Burns)
* Fix failing builds (thanks @Sam-Burns)
1.6.2 / 2016-11-21
==================
* Added support for detecting @method on interfaces that the class itself implements, or when the stubbed class is an interface itself (thanks @Seldaek)
* Added support for sebastian/recursion-context 2 (thanks @sebastianbergmann)
* Added testing on PHP 7.1 on Travis (thanks @danizord)
* Fixed the usage of the phpunit comparator (thanks @Anyqax)
1.6.1 / 2016-06-07
==================

View File

@@ -1,21 +0,0 @@
Contributing
------------
Prophecy is an open source, community-driven project. If you'd like to contribute,
feel free to do this, but remember to follow these few simple rules:
- Make your feature addition or bug fix,
- Add either specs or examples for any changes you're making (bugfixes or additions)
(please look into `spec/` folder for some examples). This is important so we don't break
it in a future version unintentionally,
- Commit your code, but do not mess with `CHANGES.md`,
Running tests
-------------
Make sure that you don't break anything with your changes by running:
```bash
$> composer install --prefer-dist
$> vendor/bin/phpspec run
```

View File

@@ -159,7 +159,7 @@ promise, there's plenty others you can use:
- `ReturnPromise` or `->willReturn(1)` - returns a value from a method call
- `ReturnArgumentPromise` or `->willReturnArgument($index)` - returns the nth method argument from call
- `ThrowPromise` or `->willThrow` - causes the method to throw specific exception
- `ThrowPromise` or `->willThrow($exception)` - causes the method to throw specific exception
- `CallbackPromise` or `->will($callback)` - gives you a quick way to define your own custom logic
Keep in mind, that you can always add even more promises by implementing

View File

@@ -19,14 +19,15 @@
"require": {
"php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
"sebastian/comparator": "^1.1",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
"sebastian/comparator": "^1.1|^2.0|^3.0",
"doctrine/instantiator": "^1.0.2",
"sebastian/recursion-context": "^1.0"
"sebastian/recursion-context": "^1.0|^2.0|^3.0"
},
"require-dev": {
"phpspec/phpspec": "^2.0"
"phpspec/phpspec": "^2.5|^3.2",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
},
"autoload": {
@@ -35,9 +36,15 @@
}
},
"autoload-dev": {
"psr-4": {
"Fixtures\\Prophecy\\": "fixtures"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.6.x-dev"
"dev-master": "1.8.x-dev"
}
}
}

View File

@@ -1,146 +0,0 @@
<?php
namespace spec\Prophecy\Argument;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument\Token\TokenInterface;
class ArgumentsWildcardSpec extends ObjectBehavior
{
/**
* @param \stdClass $object
*/
function it_wraps_non_token_arguments_into_ExactValueToken($object)
{
$this->beConstructedWith(array(42, 'zet', $object));
$class = get_class($object->getWrappedObject());
$hash = spl_object_hash($object->getWrappedObject());
$this->__toString()->shouldReturn("exact(42), exact(\"zet\"), exact($class:$hash Object (\n 'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)\n))");
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_generates_string_representation_from_all_tokens_imploded($token1, $token2, $token3)
{
$token1->__toString()->willReturn('token_1');
$token2->__toString()->willReturn('token_2');
$token3->__toString()->willReturn('token_3');
$this->beConstructedWith(array($token1, $token2, $token3));
$this->__toString()->shouldReturn('token_1, token_2, token_3');
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token
*/
function it_exposes_list_of_tokens($token)
{
$this->beConstructedWith(array($token));
$this->getTokens()->shouldReturn(array($token));
}
function it_returns_score_of_1_if_there_are_no_tokens_and_arguments()
{
$this->beConstructedWith(array());
$this->scoreArguments(array())->shouldReturn(1);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_should_return_match_score_based_on_all_tokens_score($token1, $token2, $token3)
{
$token1->scoreArgument('one')->willReturn(3);
$token1->isLast()->willReturn(false);
$token2->scoreArgument(2)->willReturn(5);
$token2->isLast()->willReturn(false);
$token3->scoreArgument($obj = new \stdClass())->willReturn(10);
$token3->isLast()->willReturn(false);
$this->beConstructedWith(array($token1, $token2, $token3));
$this->scoreArguments(array('one', 2, $obj))->shouldReturn(18);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_returns_false_if_there_is_less_arguments_than_tokens($token1, $token2, $token3)
{
$token1->scoreArgument('one')->willReturn(3);
$token1->isLast()->willReturn(false);
$token2->scoreArgument(2)->willReturn(5);
$token2->isLast()->willReturn(false);
$token3->scoreArgument(null)->willReturn(false);
$token3->isLast()->willReturn(false);
$this->beConstructedWith(array($token1, $token2, $token3));
$this->scoreArguments(array('one', 2))->shouldReturn(false);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_returns_false_if_there_is_less_tokens_than_arguments($token1, $token2, $token3)
{
$token1->scoreArgument('one')->willReturn(3);
$token1->isLast()->willReturn(false);
$token2->scoreArgument(2)->willReturn(5);
$token2->isLast()->willReturn(false);
$token3->scoreArgument($obj = new \stdClass())->willReturn(10);
$token3->isLast()->willReturn(false);
$this->beConstructedWith(array($token1, $token2, $token3));
$this->scoreArguments(array('one', 2, $obj, 4))->shouldReturn(false);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_should_return_false_if_one_of_the_tokens_returns_false($token1, $token2, $token3)
{
$token1->scoreArgument('one')->willReturn(3);
$token1->isLast()->willReturn(false);
$token2->scoreArgument(2)->willReturn(false);
$token2->isLast()->willReturn(false);
$token3->scoreArgument($obj = new \stdClass())->willReturn(10);
$token3->isLast()->willReturn(false);
$this->beConstructedWith(array($token1, $token2, $token3));
$this->scoreArguments(array('one', 2, $obj))->shouldReturn(false);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_should_calculate_score_until_last_token($token1, $token2, $token3)
{
$token1->scoreArgument('one')->willReturn(3);
$token1->isLast()->willReturn(false);
$token2->scoreArgument(2)->willReturn(7);
$token2->isLast()->willReturn(true);
$token3->scoreArgument($obj = new \stdClass())->willReturn(10);
$token3->isLast()->willReturn(false);
$this->beConstructedWith(array($token1, $token2, $token3));
$this->scoreArguments(array('one', 2, $obj))->shouldReturn(10);
}
}

View File

@@ -1,28 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class AnyValueTokenSpec extends ObjectBehavior
{
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function its_string_representation_is_star()
{
$this->__toString()->shouldReturn('*');
}
function it_scores_any_argument_as_3()
{
$this->scoreArgument(42)->shouldReturn(3);
}
}

View File

@@ -1,28 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class AnyValuesTokenSpec extends ObjectBehavior
{
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_last()
{
$this->shouldBeLast();
}
function its_string_representation_is_star_with_followup()
{
$this->__toString()->shouldReturn('* [, ...]');
}
function it_scores_any_argument_as_2()
{
$this->scoreArgument(42)->shouldReturn(2);
}
}

View File

@@ -1,55 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ApproximateValueTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith(10.12345678, 4);
}
function it_is_initializable()
{
$this->shouldHaveType('Prophecy\Argument\Token\ApproximateValueToken');
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_scores_10_if_rounded_argument_matches_rounded_value()
{
$this->scoreArgument(10.12345)->shouldReturn(10);
}
function it_does_not_score_if_rounded_argument_does_not_match_rounded_value()
{
$this->scoreArgument(10.1234)->shouldReturn(false);
}
function it_uses_a_default_precision_of_zero()
{
$this->beConstructedWith(10.7);
$this->scoreArgument(11.4)->shouldReturn(10);
}
function it_does_not_score_if_rounded_argument_is_not_numeric()
{
$this->scoreArgument('hello')->shouldReturn(false);
}
function it_has_simple_string_representation()
{
$this->__toString()->shouldBe('≅10.1235');
}
}

View File

@@ -1,64 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class ArrayCountTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith(2);
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_scores_6_if_argument_array_has_proper_count()
{
$this->scoreArgument(array(1,2))->shouldReturn(6);
}
/**
* @param \Countable $countable
*/
function it_scores_6_if_argument_countable_object_has_proper_count($countable)
{
$countable->count()->willReturn(2);
$this->scoreArgument($countable)->shouldReturn(6);
}
function it_does_not_score_if_argument_is_neither_array_nor_countable_object()
{
$this->scoreArgument('string')->shouldBe(false);
$this->scoreArgument(5)->shouldBe(false);
$this->scoreArgument(new \stdClass)->shouldBe(false);
}
function it_does_not_score_if_argument_array_has_wrong_count()
{
$this->scoreArgument(array(1))->shouldReturn(false);
}
/**
* @param \Countable $countable
*/
function it_does_not_score_if_argument_countable_object_has_wrong_count($countable)
{
$countable->count()->willReturn(3);
$this->scoreArgument($countable)->shouldReturn(false);
}
function it_has_simple_string_representation()
{
$this->__toString()->shouldBe('count(2)');
}
}

View File

@@ -1,229 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Prophecy\Exception\InvalidArgumentException;
class ArrayEntryTokenSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Argument\Token\TokenInterface $key
* @param \Prophecy\Argument\Token\TokenInterface $value
*/
function let($key, $value)
{
$this->beConstructedWith($key, $value);
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_holds_key_and_value($key, $value)
{
$this->getKey()->shouldBe($key);
$this->getValue()->shouldBe($value);
}
function its_string_representation_tells_that_its_an_array_containing_the_key_value_pair($key, $value)
{
$key->__toString()->willReturn('key');
$value->__toString()->willReturn('value');
$this->__toString()->shouldBe('[..., key => value, ...]');
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $key
* @param \stdClass $object
*/
function it_wraps_non_token_value_into_ExactValueToken($key, $object)
{
$this->beConstructedWith($key, $object);
$this->getValue()->shouldHaveType('\Prophecy\Argument\Token\ExactValueToken');
}
/**
* @param \stdClass $object
* @param \Prophecy\Argument\Token\TokenInterface $value
*/
function it_wraps_non_token_key_into_ExactValueToken($object, $value)
{
$this->beConstructedWith($object, $value);
$this->getKey()->shouldHaveType('\Prophecy\Argument\Token\ExactValueToken');
}
function it_scores_array_half_of_combined_scores_from_key_and_value_tokens($key, $value)
{
$key->scoreArgument('key')->willReturn(4);
$value->scoreArgument('value')->willReturn(6);
$this->scoreArgument(array('key'=>'value'))->shouldBe(5);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $key
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \Iterator $object
*/
function it_scores_traversable_object_half_of_combined_scores_from_key_and_value_tokens($key, $value, $object)
{
$object->current()->will(function () use ($object) {
$object->valid()->willReturn(false);
return 'value';
});
$object->key()->willReturn('key');
$object->rewind()->willReturn(null);
$object->next()->willReturn(null);
$object->valid()->willReturn(true);
$key->scoreArgument('key')->willReturn(6);
$value->scoreArgument('value')->willReturn(2);
$this->scoreArgument($object)->shouldBe(4);
}
/**
* @param \Prophecy\Argument\Token\AnyValuesToken $key
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \ArrayAccess $object
*/
function it_throws_exception_during_scoring_of_array_accessible_object_if_key_is_not_ExactValueToken($key, $value, $object)
{
$key->__toString()->willReturn('any_token');
$this->beConstructedWith($key,$value);
$errorMessage = 'You can only use exact value tokens to match key of ArrayAccess object'.PHP_EOL.
'But you used `any_token`.';
$this->shouldThrow(new InvalidArgumentException($errorMessage))->duringScoreArgument($object);
}
/**
* @param \Prophecy\Argument\Token\ExactValueToken $key
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \ArrayAccess $object
*/
function it_scores_array_accessible_object_half_of_combined_scores_from_key_and_value_tokens($key, $value, $object)
{
$object->offsetExists('key')->willReturn(true);
$object->offsetGet('key')->willReturn('value');
$key->getValue()->willReturn('key');
$key->scoreArgument('key')->willReturn(3);
$value->scoreArgument('value')->willReturn(1);
$this->scoreArgument($object)->shouldBe(2);
}
/**
* @param \Prophecy\Argument\Token\AnyValuesToken $key
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \ArrayIterator $object
*/
function it_accepts_any_key_token_type_to_score_object_that_is_both_traversable_and_array_accessible($key, $value, $object)
{
$this->beConstructedWith($key, $value);
$object->current()->will(function () use ($object) {
$object->valid()->willReturn(false);
return 'value';
});
$object->key()->willReturn('key');
$object->rewind()->willReturn(null);
$object->next()->willReturn(null);
$object->valid()->willReturn(true);
$this->shouldNotThrow(new InvalidArgumentException)->duringScoreArgument($object);
}
function it_does_not_score_if_argument_is_neither_array_nor_traversable_nor_array_accessible()
{
$this->scoreArgument('string')->shouldBe(false);
$this->scoreArgument(new \stdClass)->shouldBe(false);
}
function it_does_not_score_empty_array()
{
$this->scoreArgument(array())->shouldBe(false);
}
function it_does_not_score_array_if_key_and_value_tokens_do_not_score_same_entry($key, $value)
{
$argument = array(1 => 'foo', 2 => 'bar');
$key->scoreArgument(1)->willReturn(true);
$key->scoreArgument(2)->willReturn(false);
$value->scoreArgument('foo')->willReturn(false);
$value->scoreArgument('bar')->willReturn(true);
$this->scoreArgument($argument)->shouldBe(false);
}
/**
* @param \Iterator $object
*/
function it_does_not_score_traversable_object_without_entries($object)
{
$object->rewind()->willReturn(null);
$object->next()->willReturn(null);
$object->valid()->willReturn(false);
$this->scoreArgument($object)->shouldBe(false);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $key
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \Iterator $object
*/
function it_does_not_score_traversable_object_if_key_and_value_tokens_do_not_score_same_entry($key, $value, $object)
{
$object->current()->willReturn('foo');
$object->current()->will(function () use ($object) {
$object->valid()->willReturn(false);
return 'bar';
});
$object->key()->willReturn(1);
$object->key()->willReturn(2);
$object->rewind()->willReturn(null);
$object->next()->willReturn(null);
$object->valid()->willReturn(true);
$key->scoreArgument(1)->willReturn(true);
$key->scoreArgument(2)->willReturn(false);
$value->scoreArgument('foo')->willReturn(false);
$value->scoreArgument('bar')->willReturn(true);
$this->scoreArgument($object)->shouldBe(false);
}
/**
* @param \Prophecy\Argument\Token\ExactValueToken $key
* @param \ArrayAccess $object
*/
function it_does_not_score_array_accessible_object_if_it_has_no_offset_with_key_token_value($key, $object)
{
$object->offsetExists('key')->willReturn(false);
$key->getValue()->willReturn('key');
$this->scoreArgument($object)->shouldBe(false);
}
/**
* @param \Prophecy\Argument\Token\ExactValueToken $key
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \ArrayAccess $object
*/
function it_does_not_score_array_accessible_object_if_key_and_value_tokens_do_not_score_same_entry($key, $value, $object)
{
$object->offsetExists('key')->willReturn(true);
$object->offsetGet('key')->willReturn('value');
$key->getValue()->willReturn('key');
$value->scoreArgument('value')->willReturn(false);
$key->scoreArgument('key')->willReturn(true);
$this->scoreArgument($object)->shouldBe(false);
}
function its_score_is_capped_at_8($key, $value)
{
$key->scoreArgument('key')->willReturn(10);
$value->scoreArgument('value')->willReturn(10);
$this->scoreArgument(array('key'=>'value'))->shouldBe(8);
}
}

View File

@@ -1,109 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ArrayEveryEntryTokenSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Argument\Token\TokenInterface $value
*/
function let($value)
{
$this->beConstructedWith($value);
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_holds_value($value)
{
$this->getValue()->shouldBe($value);
}
function its_string_representation_tells_that_its_an_array_containing_only_value($value)
{
$value->__toString()->willReturn('value');
$this->__toString()->shouldBe('[value, ..., value]');
}
/**
* @param \stdClass $stdClass
*/
function it_wraps_non_token_value_into_ExactValueToken($stdClass)
{
$this->beConstructedWith($stdClass);
$this->getValue()->shouldHaveType('Prophecy\Argument\Token\ExactValueToken');
}
function it_does_not_score_if_argument_is_neither_array_nor_traversable()
{
$this->scoreArgument('string')->shouldBe(false);
$this->scoreArgument(new \stdClass)->shouldBe(false);
}
function it_does_not_score_empty_array()
{
$this->scoreArgument(array())->shouldBe(false);
}
/**
* @param \Iterator $object
*/
function it_does_not_score_traversable_object_without_entries($object)
{
$object->rewind()->willReturn(null);
$object->next()->willReturn(null);
$object->valid()->willReturn(false);
$this->scoreArgument($object)->shouldBe(false);
}
function it_scores_avg_of_scores_from_value_tokens($value)
{
$value->scoreArgument('value1')->willReturn(6);
$value->scoreArgument('value2')->willReturn(3);
$this->scoreArgument(array('value1', 'value2'))->shouldBe(4.5);
}
function it_scores_false_if_entry_scores_false($value)
{
$value->scoreArgument('value1')->willReturn(6);
$value->scoreArgument('value2')->willReturn(false);
$this->scoreArgument(array('value1', 'value2'))->shouldBe(false);
}
function it_does_not_score_array_keys($value)
{
$value->scoreArgument('value')->willReturn(6);
$value->scoreArgument('key')->shouldNotBeCalled(0);
$this->scoreArgument(array('key' => 'value'))->shouldBe(6);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $value
* @param \Iterator $object
*/
function it_scores_traversable_object_from_value_token($value, $object)
{
$object->current()->will(function ($args, $object) {
$object->valid()->willReturn(false);
return 'value';
});
$object->key()->willReturn('key');
$object->rewind()->willReturn(null);
$object->next()->willReturn(null);
$object->valid()->willReturn(true);
$value->scoreArgument('value')->willReturn(2);
$this->scoreArgument($object)->shouldBe(2);
}
}

View File

@@ -1,42 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class CallbackTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('get_class');
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_scores_7_if_argument_matches_callback()
{
$this->beConstructedWith(function ($argument) { return 2 === $argument; });
$this->scoreArgument(2)->shouldReturn(7);
}
function it_does_not_scores_if_argument_does_not_match_callback()
{
$this->beConstructedWith(function ($argument) { return 2 === $argument; });
$this->scoreArgument(5)->shouldReturn(false);
}
function its_string_representation_should_tell_that_its_callback()
{
$this->__toString()->shouldReturn('callback()');
}
}

View File

@@ -1,155 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class ExactValueTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith(42);
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_holds_value()
{
$this->getValue()->shouldReturn(42);
}
function it_scores_10_if_value_is_equal_to_argument()
{
$this->scoreArgument(42)->shouldReturn(10);
$this->scoreArgument('42')->shouldReturn(10);
}
function it_scores_10_if_value_is_an_object_and_equal_to_argument()
{
$value = new \DateTime();
$value2 = clone $value;
$this->beConstructedWith($value);
$this->scoreArgument($value2)->shouldReturn(10);
}
function it_does_not_scores_if_value_is_not_equal_to_argument()
{
$this->scoreArgument(50)->shouldReturn(false);
$this->scoreArgument(new \stdClass())->shouldReturn(false);
}
function it_does_not_scores_if_value_an_object_and_is_not_equal_to_argument()
{
$value = new ExactValueTokenFixtureB('ABC');
$value2 = new ExactValueTokenFixtureB('CBA');
$this->beConstructedWith($value);
$this->scoreArgument($value2)->shouldReturn(false);
}
function it_does_not_scores_if_value_type_and_is_not_equal_to_argument()
{
$this->beConstructedWith(false);
$this->scoreArgument(0)->shouldReturn(false);
}
function it_generates_proper_string_representation_for_integer()
{
$this->beConstructedWith(42);
$this->__toString()->shouldReturn('exact(42)');
}
function it_generates_proper_string_representation_for_string()
{
$this->beConstructedWith('some string');
$this->__toString()->shouldReturn('exact("some string")');
}
function it_generates_single_line_representation_for_multiline_string()
{
$this->beConstructedWith("some\nstring");
$this->__toString()->shouldReturn('exact("some\\nstring")');
}
function it_generates_proper_string_representation_for_double()
{
$this->beConstructedWith(42.3);
$this->__toString()->shouldReturn('exact(42.3)');
}
function it_generates_proper_string_representation_for_boolean_true()
{
$this->beConstructedWith(true);
$this->__toString()->shouldReturn('exact(true)');
}
function it_generates_proper_string_representation_for_boolean_false()
{
$this->beConstructedWith(false);
$this->__toString()->shouldReturn('exact(false)');
}
function it_generates_proper_string_representation_for_null()
{
$this->beConstructedWith(null);
$this->__toString()->shouldReturn('exact(null)');
}
function it_generates_proper_string_representation_for_empty_array()
{
$this->beConstructedWith(array());
$this->__toString()->shouldReturn('exact([])');
}
function it_generates_proper_string_representation_for_array()
{
$this->beConstructedWith(array('zet', 42));
$this->__toString()->shouldReturn('exact(["zet", 42])');
}
function it_generates_proper_string_representation_for_resource()
{
$resource = fopen(__FILE__, 'r');
$this->beConstructedWith($resource);
$this->__toString()->shouldReturn('exact(stream:'.$resource.')');
}
/**
* @param \stdClass $object
*/
function it_generates_proper_string_representation_for_object($object)
{
$objHash = sprintf('%s:%s',
get_class($object->getWrappedObject()),
spl_object_hash($object->getWrappedObject())
);
$this->beConstructedWith($object);
$this->__toString()->shouldReturn("exact($objHash Object (\n 'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)\n))");
}
}
class ExactValueTokenFixtureA
{
public $errors;
}
class ExactValueTokenFixtureB extends ExactValueTokenFixtureA
{
public $errors;
public $value = null;
public function __construct($value)
{
$this->value = $value;
}
}

View File

@@ -1,152 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class IdenticalValueTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith(42);
}
function it_is_initializable()
{
$this->shouldHaveType('Prophecy\Argument\Token\IdenticalValueToken');
}
function it_scores_11_if_string_value_is_identical_to_argument()
{
$this->beConstructedWith('foo');
$this->scoreArgument('foo')->shouldReturn(11);
}
function it_scores_11_if_boolean_value_is_identical_to_argument()
{
$this->beConstructedWith(false);
$this->scoreArgument(false)->shouldReturn(11);
}
function it_scores_11_if_integer_value_is_identical_to_argument()
{
$this->beConstructedWith(31);
$this->scoreArgument(31)->shouldReturn(11);
}
function it_scores_11_if_float_value_is_identical_to_argument()
{
$this->beConstructedWith(31.12);
$this->scoreArgument(31.12)->shouldReturn(11);
}
function it_scores_11_if_array_value_is_identical_to_argument()
{
$this->beConstructedWith(array('foo' => 'bar'));
$this->scoreArgument(array('foo' => 'bar'))->shouldReturn(11);
}
function it_scores_11_if_object_value_is_identical_to_argument()
{
$object = new \stdClass();
$this->beConstructedWith($object);
$this->scoreArgument($object)->shouldReturn(11);
}
function it_scores_false_if_value_is_not_identical_to_argument()
{
$this->beConstructedWith(new \stdClass());
$this->scoreArgument('foo')->shouldReturn(false);
}
function it_scores_false_if_object_value_is_not_the_same_instance_than_argument()
{
$this->beConstructedWith(new \stdClass());
$this->scoreArgument(new \stdClass())->shouldReturn(false);
}
function it_scores_false_if_integer_value_is_not_identical_to_boolean_argument()
{
$this->beConstructedWith(1);
$this->scoreArgument(true)->shouldReturn(false);
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_generates_proper_string_representation_for_integer()
{
$this->beConstructedWith(42);
$this->__toString()->shouldReturn('identical(42)');
}
function it_generates_proper_string_representation_for_string()
{
$this->beConstructedWith('some string');
$this->__toString()->shouldReturn('identical("some string")');
}
function it_generates_single_line_representation_for_multiline_string()
{
$this->beConstructedWith("some\nstring");
$this->__toString()->shouldReturn('identical("some\\nstring")');
}
function it_generates_proper_string_representation_for_double()
{
$this->beConstructedWith(42.3);
$this->__toString()->shouldReturn('identical(42.3)');
}
function it_generates_proper_string_representation_for_boolean_true()
{
$this->beConstructedWith(true);
$this->__toString()->shouldReturn('identical(true)');
}
function it_generates_proper_string_representation_for_boolean_false()
{
$this->beConstructedWith(false);
$this->__toString()->shouldReturn('identical(false)');
}
function it_generates_proper_string_representation_for_null()
{
$this->beConstructedWith(null);
$this->__toString()->shouldReturn('identical(null)');
}
function it_generates_proper_string_representation_for_empty_array()
{
$this->beConstructedWith(array());
$this->__toString()->shouldReturn('identical([])');
}
function it_generates_proper_string_representation_for_array()
{
$this->beConstructedWith(array('zet', 42));
$this->__toString()->shouldReturn('identical(["zet", 42])');
}
function it_generates_proper_string_representation_for_resource()
{
$resource = fopen(__FILE__, 'r');
$this->beConstructedWith($resource);
$this->__toString()->shouldReturn('identical(stream:'.$resource.')');
}
function it_generates_proper_string_representation_for_object($object)
{
$objHash = sprintf('%s:%s',
get_class($object->getWrappedObject()),
spl_object_hash($object->getWrappedObject())
);
$this->beConstructedWith($object);
$this->__toString()->shouldReturn("identical($objHash Object (\n 'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)\n))");
}
}

View File

@@ -1,78 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class LogicalAndTokenSpec extends ObjectBehavior
{
function it_implements_TokenInterface()
{
$this->beConstructedWith(array());
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->beConstructedWith(array());
$this->shouldNotBeLast();
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
* @param \Prophecy\Argument\Token\TokenInterface $token3
*/
function it_generates_string_representation_from_all_tokens_imploded($token1, $token2, $token3)
{
$token1->__toString()->willReturn('token_1');
$token2->__toString()->willReturn('token_2');
$token3->__toString()->willReturn('token_3');
$this->beConstructedWith(array($token1, $token2, $token3));
$this->__toString()->shouldReturn('bool(token_1 AND token_2 AND token_3)');
}
function it_wraps_non_token_arguments_into_ExactValueToken()
{
$this->beConstructedWith(array(15, '1985'));
$this->__toString()->shouldReturn("bool(exact(15) AND exact(\"1985\"))");
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
*/
function it_scores_the_maximum_score_from_all_scores_returned_by_tokens($token1, $token2)
{
$token1->scoreArgument(1)->willReturn(10);
$token2->scoreArgument(1)->willReturn(5);
$this->beConstructedWith(array($token1, $token2));
$this->scoreArgument(1)->shouldReturn(10);
}
function it_does_not_score_if_there_are_no_arguments_or_tokens()
{
$this->beConstructedWith(array());
$this->scoreArgument('any')->shouldReturn(false);
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $token1
* @param \Prophecy\Argument\Token\TokenInterface $token2
*/
function it_does_not_score_if_either_of_tokens_does_not_score($token1, $token2)
{
$token1->scoreArgument(1)->willReturn(10);
$token1->scoreArgument(2)->willReturn(false);
$token2->scoreArgument(1)->willReturn(false);
$token2->scoreArgument(2)->willReturn(10);
$this->beConstructedWith(array($token1, $token2));
$this->scoreArgument(1)->shouldReturn(false);
$this->scoreArgument(2)->shouldReturn(false);
}
}

View File

@@ -1,65 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument\Token\TokenInterface;
class LogicalNotTokenSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Argument\Token\TokenInterface $token
*/
function let($token)
{
$this->beConstructedWith($token);
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_holds_originating_token($token)
{
$this->getOriginatingToken()->shouldReturn($token);
}
function it_has_simple_string_representation($token)
{
$token->__toString()->willReturn('value');
$this->__toString()->shouldBe('not(value)');
}
function it_wraps_non_token_argument_into_ExactValueToken()
{
$this->beConstructedWith(5);
$token = $this->getOriginatingToken();
$token->shouldhaveType('Prophecy\Argument\Token\ExactValueToken');
$token->getValue()->shouldBe(5);
}
function it_scores_4_if_preset_token_does_not_match_the_argument($token)
{
$token->scoreArgument('argument')->willReturn(false);
$this->scoreArgument('argument')->shouldBe(4);
}
function it_does_not_score_if_preset_token_matches_argument($token)
{
$token->scoreArgument('argument')->willReturn(5);
$this->scoreArgument('argument')->shouldBe(false);
}
function it_is_last_if_preset_token_is_last($token)
{
$token->isLast()->willReturn(true);
$this->shouldBeLast();
}
function it_is_not_last_if_preset_token_is_not_last($token)
{
$token->isLast()->willReturn(false);
$this->shouldNotBeLast();
}
}

View File

@@ -1,101 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class ObjectStateTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('getName', 'stdClass');
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
/**
* @param \ReflectionClass $reflection
*/
function it_scores_8_if_argument_object_has_specific_method_state($reflection)
{
$reflection->getName()->willReturn('stdClass');
$this->scoreArgument($reflection)->shouldReturn(8);
}
/**
* @param \stdClass $class
*/
function it_scores_8_if_argument_object_has_specific_property_state($class)
{
$class->getName = 'stdClass';
$this->scoreArgument($class)->shouldReturn(8);
}
function it_does_not_score_if_argument_method_state_does_not_match()
{
$value = new ObjectStateTokenFixtureB('ABC');
$value2 = new ObjectStateTokenFixtureB('CBA');
$this->beConstructedWith('getSelf', $value);
$this->scoreArgument($value2)->shouldReturn(false);
}
/**
* @param \stdClass $class
*/
function it_does_not_score_if_argument_property_state_does_not_match($class)
{
$class->getName = 'SplFileInfo';
$this->scoreArgument($class)->shouldReturn(false);
}
/**
* @param \spec\Prophecy\Argument\Token\ObjectStateTokenFixtureA $class
*/
function it_does_not_score_if_argument_object_does_not_have_method_or_property($class)
{
$this->scoreArgument($class)->shouldReturn(false);
}
function it_does_not_score_if_argument_is_not_object()
{
$this->scoreArgument(42)->shouldReturn(false);
}
function it_has_simple_string_representation()
{
$this->__toString()->shouldReturn('state(getName(), "stdClass")');
}
}
class ObjectStateTokenFixtureA
{
public $errors;
}
class ObjectStateTokenFixtureB extends ObjectStateTokenFixtureA
{
public $errors;
public $value = null;
public function __construct($value)
{
$this->value = $value;
}
public function getSelf()
{
return $this;
}
}

View File

@@ -1,49 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class StringContainsTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('a substring');
}
function it_is_initializable()
{
$this->shouldHaveType('Prophecy\Argument\Token\StringContainsToken');
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_holds_value()
{
$this->getValue()->shouldReturn('a substring');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_scores_6_if_the_argument_contains_the_value()
{
$this->scoreArgument('Argument containing a substring')->shouldReturn(6);
}
function it_does_not_score_if_the_argument_does_not_contain_the_value()
{
$this->scoreArgument('Argument will not match')->shouldReturn(false);
}
function its_string_representation_shows_substring()
{
$this->__toString()->shouldReturn('contains("a substring")');
}
}

View File

@@ -1,62 +0,0 @@
<?php
namespace spec\Prophecy\Argument\Token;
use PhpSpec\ObjectBehavior;
class TypeTokenSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('integer');
}
function it_implements_TokenInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Argument\Token\TokenInterface');
}
function it_is_not_last()
{
$this->shouldNotBeLast();
}
function it_scores_5_if_argument_matches_simple_type()
{
$this->beConstructedWith('integer');
$this->scoreArgument(42)->shouldReturn(5);
}
function it_does_not_scores_if_argument_does_not_match_simple_type()
{
$this->beConstructedWith('integer');
$this->scoreArgument(42.0)->shouldReturn(false);
}
/**
* @param \ReflectionObject $object
*/
function it_scores_5_if_argument_is_an_instance_of_specified_class($object)
{
$this->beConstructedWith('ReflectionClass');
$this->scoreArgument($object)->shouldReturn(5);
}
function it_has_simple_string_representation()
{
$this->__toString()->shouldReturn('type(integer)');
}
/**
* @param \Prophecy\Argument\Token\TokenInterface $interface
*/
function it_scores_5_if_argument_is_an_instance_of_specified_interface($interface)
{
$this->beConstructedWith('Prophecy\Argument\Token\TokenInterface');
$this->scoreArgument($interface)->shouldReturn(5);
}
}

View File

@@ -1,107 +0,0 @@
<?php
namespace spec\Prophecy;
use PhpSpec\ObjectBehavior;
class ArgumentSpec extends ObjectBehavior
{
function it_has_a_shortcut_for_exact_argument_token()
{
$token = $this->exact(42);
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ExactValueToken');
$token->getValue()->shouldReturn(42);
}
function it_has_a_shortcut_for_any_argument_token()
{
$token = $this->any();
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\AnyValueToken');
}
function it_has_a_shortcut_for_multiple_arguments_token()
{
$token = $this->cetera();
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\AnyValuesToken');
}
function it_has_a_shortcut_for_type_token()
{
$token = $this->type('integer');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\TypeToken');
}
function it_has_a_shortcut_for_callback_token()
{
$token = $this->that('get_class');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\CallbackToken');
}
function it_has_a_shortcut_for_object_state_token()
{
$token = $this->which('getName', 'everzet');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ObjectStateToken');
}
function it_has_a_shortcut_for_logical_and_token()
{
$token = $this->allOf('integer', 5);
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\LogicalAndToken');
}
function it_has_a_shortcut_for_array_count_token()
{
$token = $this->size(5);
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ArrayCountToken');
}
function it_has_a_shortcut_for_array_entry_token()
{
$token = $this->withEntry('key', 'value');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ArrayEntryToken');
}
function it_has_a_shortcut_for_array_every_entry_token()
{
$token = $this->withEveryEntry('value');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ArrayEveryEntryToken');
}
function it_has_a_shortcut_for_identical_value_token()
{
$token = $this->is('value');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\IdenticalValueToken');
}
function it_has_a_shortcut_for_array_entry_token_matching_any_key()
{
$token = $this->containing('value');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ArrayEntryToken');
$token->getKey()->shouldHaveType('Prophecy\Argument\Token\AnyValueToken');
}
function it_has_a_shortcut_for_array_entry_token_matching_any_value()
{
$token = $this->withKey('key');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ArrayEntryToken');
$token->getValue()->shouldHaveType('Prophecy\Argument\Token\AnyValueToken');
}
function it_has_a_shortcut_for_logical_not_token()
{
$token = $this->not('kagux');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\LogicalNotToken');
}
function it_has_a_shortcut_for_string_contains_token()
{
$token = $this->containingString('string');
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\StringContainsToken');
}
function it_has_a_shortcut_for_approximate_token()
{
$token = $this->approximate(10);
$token->shouldBeAnInstanceOf('Prophecy\Argument\Token\ApproximateValueToken');
}
}

View File

@@ -1,195 +0,0 @@
<?php
namespace spec\Prophecy\Call;
use PhpSpec\ObjectBehavior;
use Prophecy\Prophecy\ObjectProphecy;
use Prophecy\Argument\ArgumentsWildcard;
class CallCenterSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Prophecy\ObjectProphecy $objectProphecy
*/
function let($objectProphecy)
{
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $objectProphecy
* @param \Prophecy\Argument\ArgumentsWildcard $wildcard
*/
function it_records_calls_made_through_makeCall_method($objectProphecy, $wildcard)
{
$wildcard->scoreArguments(array(5, 2, 3))->willReturn(10);
$objectProphecy->getMethodProphecies()->willReturn(array());
$this->makeCall($objectProphecy, 'setValues', array(5, 2, 3));
$calls = $this->findCalls('setValues', $wildcard);
$calls->shouldHaveCount(1);
$calls[0]->shouldBeAnInstanceOf('Prophecy\Call\Call');
$calls[0]->getMethodName()->shouldReturn('setValues');
$calls[0]->getArguments()->shouldReturn(array(5, 2, 3));
$calls[0]->getReturnValue()->shouldReturn(null);
}
function it_returns_null_for_any_call_through_makeCall_if_no_method_prophecies_added(
$objectProphecy
)
{
$objectProphecy->getMethodProphecies()->willReturn(array());
$this->makeCall($objectProphecy, 'setValues', array(5, 2, 3))->shouldReturn(null);
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $method1
* @param \Prophecy\Prophecy\MethodProphecy $method2
* @param \Prophecy\Prophecy\MethodProphecy $method3
* @param \Prophecy\Argument\ArgumentsWildcard $arguments1
* @param \Prophecy\Argument\ArgumentsWildcard $arguments2
* @param \Prophecy\Argument\ArgumentsWildcard $arguments3
* @param \Prophecy\Promise\PromiseInterface $promise
*/
function it_executes_promise_of_method_prophecy_that_matches_signature_passed_to_makeCall(
$objectProphecy, $method1, $method2, $method3, $arguments1, $arguments2, $arguments3,
$promise
)
{
$method1->getMethodName()->willReturn('getName');
$method1->getArgumentsWildcard()->willReturn($arguments1);
$arguments1->scoreArguments(array('world', 'everything'))->willReturn(false);
$method2->getMethodName()->willReturn('setTitle');
$method2->getArgumentsWildcard()->willReturn($arguments2);
$arguments2->scoreArguments(array('world', 'everything'))->willReturn(false);
$method3->getMethodName()->willReturn('getName');
$method3->getArgumentsWildcard()->willReturn($arguments3);
$method3->getPromise()->willReturn($promise);
$arguments3->scoreArguments(array('world', 'everything'))->willReturn(200);
$objectProphecy->getMethodProphecies()->willReturn(array(
'method1' => array($method1),
'method2' => array($method2, $method3)
));
$objectProphecy->getMethodProphecies('getName')->willReturn(array($method1, $method3));
$objectProphecy->reveal()->willReturn(new \stdClass());
$promise->execute(array('world', 'everything'), $objectProphecy->getWrappedObject(), $method3)->willReturn(42);
$this->makeCall($objectProphecy, 'getName', array('world', 'everything'))->shouldReturn(42);
$calls = $this->findCalls('getName', $arguments3);
$calls->shouldHaveCount(1);
$calls[0]->getReturnValue()->shouldReturn(42);
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $method1
* @param \Prophecy\Prophecy\MethodProphecy $method2
* @param \Prophecy\Prophecy\MethodProphecy $method3
* @param \Prophecy\Argument\ArgumentsWildcard $arguments1
* @param \Prophecy\Argument\ArgumentsWildcard $arguments2
* @param \Prophecy\Argument\ArgumentsWildcard $arguments3
* @param \Prophecy\Promise\PromiseInterface $promise
*/
function it_executes_promise_of_method_prophecy_that_matches_with_highest_score_to_makeCall(
$objectProphecy, $method1, $method2, $method3, $arguments1, $arguments2, $arguments3,
$promise
)
{
$method1->getMethodName()->willReturn('getName');
$method1->getArgumentsWildcard()->willReturn($arguments1);
$arguments1->scoreArguments(array('world', 'everything'))->willReturn(50);
$method2->getMethodName()->willReturn('getName');
$method2->getArgumentsWildcard()->willReturn($arguments2);
$method2->getPromise()->willReturn($promise);
$arguments2->scoreArguments(array('world', 'everything'))->willReturn(300);
$method3->getMethodName()->willReturn('getName');
$method3->getArgumentsWildcard()->willReturn($arguments3);
$arguments3->scoreArguments(array('world', 'everything'))->willReturn(200);
$objectProphecy->getMethodProphecies()->willReturn(array(
'method1' => array($method1),
'method2' => array($method2, $method3)
));
$objectProphecy->getMethodProphecies('getName')->willReturn(array(
$method1, $method2, $method3
));
$objectProphecy->reveal()->willReturn(new \stdClass());
$promise->execute(array('world', 'everything'), $objectProphecy->getWrappedObject(), $method2)
->willReturn('second');
$this->makeCall($objectProphecy, 'getName', array('world', 'everything'))
->shouldReturn('second');
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $method
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
*/
function it_throws_exception_if_call_does_not_match_any_of_defined_method_prophecies(
$objectProphecy, $method, $arguments
)
{
$method->getMethodName()->willReturn('getName');
$method->getArgumentsWildcard()->willReturn($arguments);
$arguments->scoreArguments(array('world', 'everything'))->willReturn(false);
$arguments->__toString()->willReturn('arg1, arg2');
$objectProphecy->getMethodProphecies()->willReturn(array('method1' => array($method)));
$objectProphecy->getMethodProphecies('getName')->willReturn(array($method));
$this->shouldThrow('Prophecy\Exception\Call\UnexpectedCallException')
->duringMakeCall($objectProphecy, 'getName', array('world', 'everything'));
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $method
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
*/
function it_returns_null_if_method_prophecy_that_matches_makeCall_arguments_has_no_promise(
$objectProphecy, $method, $arguments
)
{
$method->getMethodName()->willReturn('getName');
$method->getArgumentsWildcard()->willReturn($arguments);
$method->getPromise()->willReturn(null);
$arguments->scoreArguments(array('world', 'everything'))->willReturn(100);
$objectProphecy->getMethodProphecies()->willReturn(array($method));
$objectProphecy->getMethodProphecies('getName')->willReturn(array($method));
$this->makeCall($objectProphecy, 'getName', array('world', 'everything'))
->shouldReturn(null);
}
/**
* @param \Prophecy\Argument\ArgumentsWildcard $wildcard
*/
function it_finds_recorded_calls_by_a_method_name_and_arguments_wildcard(
$objectProphecy, $wildcard
)
{
$objectProphecy->getMethodProphecies()->willReturn(array());
$this->makeCall($objectProphecy, 'getName', array('world'));
$this->makeCall($objectProphecy, 'getName', array('everything'));
$this->makeCall($objectProphecy, 'setName', array(42));
$wildcard->scoreArguments(array('world'))->willReturn(false);
$wildcard->scoreArguments(array('everything'))->willReturn(10);
$calls = $this->findCalls('getName', $wildcard);
$calls->shouldHaveCount(1);
$calls[0]->getMethodName()->shouldReturn('getName');
$calls[0]->getArguments()->shouldReturn(array('everything'));
}
}

View File

@@ -1,54 +0,0 @@
<?php
namespace spec\Prophecy\Call;
use PhpSpec\ObjectBehavior;
class CallSpec extends ObjectBehavior
{
/**
* @param \Exception $exception
*/
function let($exception)
{
$this->beConstructedWith('setValues', array(5, 2), 42, $exception, 'some_file.php', 23);
}
function it_exposes_method_name_through_getter()
{
$this->getMethodName()->shouldReturn('setValues');
}
function it_exposes_arguments_through_getter()
{
$this->getArguments()->shouldReturn(array(5, 2));
}
function it_exposes_return_value_through_getter()
{
$this->getReturnValue()->shouldReturn(42);
}
function it_exposes_exception_through_getter($exception)
{
$this->getException()->shouldReturn($exception);
}
function it_exposes_file_and_line_through_getter()
{
$this->getFile()->shouldReturn('some_file.php');
$this->getLine()->shouldReturn(23);
}
function it_returns_shortpath_to_callPlace()
{
$this->getCallPlace()->shouldReturn('some_file.php:23');
}
function it_returns_unknown_as_callPlace_if_no_file_or_line_provided()
{
$this->beConstructedWith('setValues', array(), 0, null, null, null);
$this->getCallPlace()->shouldReturn('unknown');
}
}

View File

@@ -1,39 +0,0 @@
<?php
namespace spec\Prophecy\Comparator;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ClosureComparatorSpec extends ObjectBehavior
{
function it_is_comparator()
{
$this->shouldHaveType('SebastianBergmann\Comparator\Comparator');
}
function it_accepts_only_closures()
{
$this->accepts(123, 321)->shouldReturn(false);
$this->accepts('string', 'string')->shouldReturn(false);
$this->accepts(false, true)->shouldReturn(false);
$this->accepts(true, false)->shouldReturn(false);
$this->accepts((object)array(), (object)array())->shouldReturn(false);
$this->accepts(function(){}, (object)array())->shouldReturn(false);
$this->accepts(function(){}, (object)array())->shouldReturn(false);
$this->accepts(function(){}, function(){})->shouldReturn(true);
}
function it_asserts_that_all_closures_are_different()
{
$this->shouldThrow()->duringAssertEquals(function(){}, function(){});
}
function it_asserts_that_all_closures_are_different_even_if_its_the_same_closure()
{
$closure = function(){};
$this->shouldThrow()->duringAssertEquals($closure, $closure);
}
}

View File

@@ -1,20 +0,0 @@
<?php
namespace spec\Prophecy\Comparator;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class FactorySpec extends ObjectBehavior
{
function it_extends_Sebastian_Comparator_Factory()
{
$this->shouldHaveType('SebastianBergmann\Comparator\Factory');
}
function it_should_have_ClosureComparator_registered()
{
$comparator = $this->getInstance()->getComparatorFor(function(){}, function(){});
$comparator->shouldHaveType('Prophecy\Comparator\ClosureComparator');
}
}

View File

@@ -1,39 +0,0 @@
<?php
namespace spec\Prophecy\Comparator;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Prophecy\Prophet;
class ProphecyComparatorSpec extends ObjectBehavior
{
function it_is_a_comparator()
{
$this->shouldHaveType('SebastianBergmann\Comparator\ObjectComparator');
}
function it_accepts_only_prophecy_objects()
{
$this->accepts(123, 321)->shouldReturn(false);
$this->accepts('string', 'string')->shouldReturn(false);
$this->accepts(false, true)->shouldReturn(false);
$this->accepts(true, false)->shouldReturn(false);
$this->accepts((object)array(), (object)array())->shouldReturn(false);
$this->accepts(function(){}, (object)array())->shouldReturn(false);
$this->accepts(function(){}, function(){})->shouldReturn(false);
$prophet = new Prophet();
$prophecy = $prophet->prophesize('Prophecy\Prophecy\ObjectProphecy');
$this->accepts($prophecy, $prophecy)->shouldReturn(true);
}
function it_asserts_that_an_object_is_equal_to_its_revealed_prophecy()
{
$prophet = new Prophet();
$prophecy = $prophet->prophesize('Prophecy\Prophecy\ObjectProphecy');
$this->shouldNotThrow()->duringAssertEquals($prophecy->reveal(), $prophecy);
}
}

View File

@@ -1,59 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class DisableConstructorPatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
function its_priority_is_100()
{
$this->getPriority()->shouldReturn(100);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_supports_anything($node)
{
$this->supports($node)->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $arg1
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $arg2
*/
function it_makes_all_constructor_arguments_optional($class, $method, $arg1, $arg2)
{
$class->hasMethod('__construct')->willReturn(true);
$class->getMethod('__construct')->willReturn($method);
$method->getArguments()->willReturn(array($arg1, $arg2));
$arg1->setDefault(null)->shouldBeCalled();
$arg2->setDefault(null)->shouldBeCalled();
$method->setCode(Argument::type('string'))->shouldBeCalled();
$this->apply($class);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
*/
function it_creates_new_constructor_if_object_has_none($class)
{
$class->hasMethod('__construct')->willReturn(false);
$class->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'))
->shouldBeCalled();
$this->apply($class);
}
}

View File

@@ -1,37 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class HhvmExceptionPatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
function its_priority_is_minus_50()
{
$this->getPriority()->shouldReturn(-50);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
* @param \Prophecy\Doubler\Generator\Node\MethodNode $getterMethod
*/
function it_uses_parent_code_for_setTraceOptions($node, $method, $getterMethod)
{
$node->hasMethod('setTraceOptions')->willReturn(true);
$node->getMethod('setTraceOptions')->willReturn($method);
$node->hasMethod('getTraceOptions')->willReturn(true);
$node->getMethod('getTraceOptions')->willReturn($getterMethod);
$method->useParentCode()->shouldBeCalled();
$getterMethod->useParentCode()->shouldBeCalled();
$this->apply($node);
}
}

View File

@@ -1,44 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Prophecy\Doubler\Generator\Node\MethodNode;
class KeywordPatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
function its_priority_is_49()
{
$this->getPriority()->shouldReturn(49);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method1
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method2
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method3
*/
function it_will_remove_echo_and_eval_methods($node, $method1, $method2, $method3)
{
$node->removeMethod('eval')->shouldBeCalled();
$node->removeMethod('echo')->shouldBeCalled();
$method1->getName()->willReturn('echo');
$method2->getName()->willReturn('eval');
$method3->getName()->willReturn('notKeyword');
$node->getMethods()->willReturn(array(
'echo' => $method1,
'eval' => $method2,
'notKeyword' => $method3,
));
$this->apply($node);
}
}

View File

@@ -1,125 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Prophecy\Doubler\Generator\Node\MethodNode;
class MagicCallPatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_supports_anything($node)
{
$this->supports($node)->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_discovers_api_using_phpdoc($node)
{
$node->getParentClass()->willReturn('spec\Prophecy\Doubler\ClassPatch\MagicalApi');
$node->addMethod(new MethodNode('undefinedMethod'))->shouldBeCalled();
$this->apply($node);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_ignores_existing_methods($node)
{
$node->getParentClass()->willReturn('spec\Prophecy\Doubler\ClassPatch\MagicalApiExtended');
$node->addMethod(new MethodNode('undefinedMethod'))->shouldBeCalled();
$node->addMethod(new MethodNode('definedMethod'))->shouldNotBeCalled();
$this->apply($node);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_ignores_empty_methods_from_phpdoc($node)
{
$node->getParentClass()->willReturn('spec\Prophecy\Doubler\ClassPatch\MagicalApiInvalidMethodDefinition');
$node->addMethod(new MethodNode(''))->shouldNotBeCalled();
$this->apply($node);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_discovers_api_using_phpdoc_from_interface($node)
{
$node->getParentClass()->willReturn('spec\Prophecy\Doubler\ClassPatch\MagicalApiImplemented');
$node->addMethod(new MethodNode('implementedMethod'))->shouldBeCalled();
$this->apply($node);
}
function it_has_50_priority()
{
$this->getPriority()->shouldReturn(50);
}
}
/**
* @method void undefinedMethod()
*/
class MagicalApi
{
/**
* @return void
*/
public function definedMethod()
{
}
}
/**
* @method void invalidMethodDefinition
* @method void
* @method
*/
class MagicalApiInvalidMethodDefinition
{
}
/**
* @method void undefinedMethod()
* @method void definedMethod()
*/
class MagicalApiExtended extends MagicalApi
{
}
/**
*/
class MagicalApiImplemented implements MagicalApiInterface
{
}
/**
* @method void implementedMethod()
*/
interface MagicalApiInterface
{
}

View File

@@ -1,83 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ProphecySubjectPatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
function it_has_priority_of_0()
{
$this->getPriority()->shouldReturn(0);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_supports_any_class($node)
{
$this->supports($node)->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_forces_class_to_implement_ProphecySubjectInterface($node)
{
$node->addInterface('Prophecy\Prophecy\ProphecySubjectInterface')->shouldBeCalled();
$node->addProperty('objectProphecy', 'private')->willReturn(null);
$node->getMethods()->willReturn(array());
$node->hasMethod(Argument::any())->willReturn(false);
$node->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'))->willReturn(null);
$node->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'))->willReturn(null);
$this->apply($node);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
* @param \Prophecy\Doubler\Generator\Node\MethodNode $constructor
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method1
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method2
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method3
*/
function it_forces_all_class_methods_except_constructor_to_proxy_calls_into_prophecy_makeCall(
$node, $constructor, $method1, $method2, $method3
)
{
$node->addInterface('Prophecy\Prophecy\ProphecySubjectInterface')->willReturn(null);
$node->addProperty('objectProphecy', 'private')->willReturn(null);
$node->hasMethod(Argument::any())->willReturn(false);
$node->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'))->willReturn(null);
$node->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'))->willReturn(null);
$constructor->getName()->willReturn('__construct');
$method1->getName()->willReturn('method1');
$method2->getName()->willReturn('method2');
$method3->getName()->willReturn('method3');
$node->getMethods()->willReturn(array(
'method1' => $method1,
'method2' => $method2,
'method3' => $method3,
));
$constructor->setCode(Argument::any())->shouldNotBeCalled();
$method1->setCode('return $this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());')
->shouldBeCalled();
$method2->setCode('return $this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());')
->shouldBeCalled();
$method3->setCode('return $this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());')
->shouldBeCalled();
$this->apply($node);
}
}

View File

@@ -1,47 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ReflectionClassNewInstancePatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
function its_priority_is_50()
{
$this->getPriority()->shouldReturn(50);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $reflectionClassNode
* @param \Prophecy\Doubler\Generator\Node\ClassNode $anotherClassNode
*/
function it_supports_ReflectionClass_only($reflectionClassNode, $anotherClassNode)
{
$reflectionClassNode->getParentClass()->willReturn('ReflectionClass');
$anotherClassNode->getParentClass()->willReturn('stdClass');
$this->supports($reflectionClassNode)->shouldReturn(true);
$this->supports($anotherClassNode)->shouldReturn(false);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $arg1
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $arg2
*/
function it_makes_all_newInstance_arguments_optional($class, $method, $arg1, $arg2)
{
$class->getMethod('newInstance')->willReturn($method);
$method->getArguments()->willReturn(array($arg1));
$arg1->setDefault(null)->shouldBeCalled();
$this->apply($class);
}
}

View File

@@ -1,107 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class SplFileInfoPatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
function its_priority_is_50()
{
$this->getPriority()->shouldReturn(50);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_does_not_support_nodes_without_parent_class($node)
{
$node->getParentClass()->willReturn('stdClass');
$this->supports($node)->shouldReturn(false);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_supports_nodes_with_SplFileInfo_as_parent_class($node)
{
$node->getParentClass()->willReturn('SplFileInfo');
$this->supports($node)->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_supports_nodes_with_derivative_of_SplFileInfo_as_parent_class($node)
{
$node->getParentClass()->willReturn('SplFileInfo');
$this->supports($node)->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_adds_a_method_to_node_if_not_exists($node)
{
$node->hasMethod('__construct')->willReturn(false);
$node->addMethod(Argument::any())->shouldBeCalled();
$node->getParentClass()->shouldBeCalled();
$this->apply($node);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
*/
function it_updates_existing_method_if_found($node, $method)
{
$node->hasMethod('__construct')->willReturn(true);
$node->getMethod('__construct')->willReturn($method);
$node->getParentClass()->shouldBeCalled();
$method->useParentCode()->shouldBeCalled();
$this->apply($node);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
*/
function it_should_not_supply_a_file_for_a_directory_iterator($node, $method)
{
$node->hasMethod('__construct')->willReturn(true);
$node->getMethod('__construct')->willReturn($method);
$node->getParentClass()->willReturn('DirectoryIterator');
$method->setCode(Argument::that(function($value) {
return strpos($value, '.php') === false;
}))->shouldBeCalled();
$this->apply($node);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
*/
function it_should_supply_a_file_for_a_spl_file_object($node, $method)
{
$node->hasMethod('__construct')->willReturn(true);
$node->getMethod('__construct')->willReturn($method);
$node->getParentClass()->willReturn('SplFileObject');
$method->setCode(Argument::that(function($value) {
return strpos($value, '.php') !== false;
}))->shouldBeCalled();
$this->apply($node);
}
}

View File

@@ -1,61 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\ClassPatch;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class TraversablePatchSpec extends ObjectBehavior
{
function it_is_a_patch()
{
$this->shouldBeAnInstanceOf('Prophecy\Doubler\ClassPatch\ClassPatchInterface');
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_supports_class_that_implements_only_Traversable($node)
{
$node->getInterfaces()->willReturn(array('Traversable'));
$this->supports($node)->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_does_not_support_class_that_implements_Iterator($node)
{
$node->getInterfaces()->willReturn(array('Traversable', 'Iterator'));
$this->supports($node)->shouldReturn(false);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_does_not_support_class_that_implements_IteratorAggregate($node)
{
$node->getInterfaces()->willReturn(array('Traversable', 'IteratorAggregate'));
$this->supports($node)->shouldReturn(false);
}
function it_has_100_priority()
{
$this->getPriority()->shouldReturn(100);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_forces_node_to_implement_IteratorAggregate($node)
{
$node->addInterface('Iterator')->shouldBeCalled();
$node->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'))->willReturn(null);
$this->apply($node);
}
}

View File

@@ -1,122 +0,0 @@
<?php
namespace spec\Prophecy\Doubler;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class DoublerSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Doubler\Generator\ClassMirror $mirror
* @param \Prophecy\Doubler\Generator\ClassCreator $creator
* @param \Prophecy\Doubler\NameGenerator $namer
*/
function let($mirror, $creator, $namer)
{
$this->beConstructedWith($mirror, $creator, $namer);
}
function it_does_not_have_patches_by_default()
{
$this->getClassPatches()->shouldHaveCount(0);
}
/**
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $patch
*/
function its_registerClassPatch_adds_a_patch_to_the_doubler($patch)
{
$this->registerClassPatch($patch);
$this->getClassPatches()->shouldReturn(array($patch));
}
/**
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $alt1
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $alt2
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $alt3
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $alt4
*/
function its_getClassPatches_sorts_patches_by_priority($alt1, $alt2, $alt3, $alt4)
{
$alt1->getPriority()->willReturn(2);
$alt2->getPriority()->willReturn(50);
$alt3->getPriority()->willReturn(10);
$alt4->getPriority()->willReturn(0);
$this->registerClassPatch($alt1);
$this->registerClassPatch($alt2);
$this->registerClassPatch($alt3);
$this->registerClassPatch($alt4);
$this->getClassPatches()->shouldReturn(array($alt2, $alt3, $alt1, $alt4));
}
/**
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $alt1
* @param \Prophecy\Doubler\ClassPatch\ClassPatchInterface $alt2
* @param \ReflectionClass $class
* @param \ReflectionClass $interface1
* @param \ReflectionClass $interface2
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function its_double_mirrors_alterates_and_instantiates_provided_class(
$mirror, $creator, $namer, $alt1, $alt2, $class, $interface1, $interface2, $node
)
{
$mirror->reflect($class, array($interface1, $interface2))->willReturn($node);
$alt1->supports($node)->willReturn(true);
$alt2->supports($node)->willReturn(false);
$alt1->getPriority()->willReturn(1);
$alt2->getPriority()->willReturn(2);
$namer->name($class, array($interface1, $interface2))->willReturn('SplStack');
$class->getName()->willReturn('stdClass');
$interface1->getName()->willReturn('ArrayAccess');
$interface2->getName()->willReturn('Iterator');
$alt1->apply($node)->shouldBeCalled();
$alt2->apply($node)->shouldNotBeCalled();
$creator->create('SplStack', $node)->shouldBeCalled();
$this->registerClassPatch($alt1);
$this->registerClassPatch($alt2);
$this->double($class, array($interface1, $interface2))
->shouldReturnAnInstanceOf('SplStack');
}
/**
* @param \ReflectionClass $class
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_double_instantiates_a_class_with_constructor_argument($mirror, $class, $node, $namer)
{
$class->getName()->willReturn('ReflectionClass');
$mirror->reflect($class, array())->willReturn($node);
$namer->name($class, array())->willReturn('ReflectionClass');
$double = $this->double($class, array(), array('stdClass'));
$double->shouldBeAnInstanceOf('ReflectionClass');
$double->getName()->shouldReturn('stdClass');
}
/**
* @param \ReflectionClass $class
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function it_can_instantiate_class_with_final_constructor($mirror, $class, $node, $namer)
{
$class->getName()->willReturn('spec\Prophecy\Doubler\WithFinalConstructor');
$mirror->reflect($class, array())->willReturn($node);
$namer->name($class, array())->willReturn('spec\Prophecy\Doubler\WithFinalConstructor');
$double = $this->double($class, array());
$double->shouldBeAnInstanceOf('spec\Prophecy\Doubler\WithFinalConstructor');
}
}
class WithFinalConstructor
{
final public function __construct() {}
}

View File

@@ -1,323 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\Generator;
use PhpSpec\ObjectBehavior;
class ClassCodeGeneratorSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method1
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method2
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method3
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument11
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument12
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument21
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument31
*/
function it_generates_proper_php_code_for_specific_ClassNode(
$class, $method1, $method2, $method3, $argument11, $argument12, $argument21, $argument31
)
{
$class->getParentClass()->willReturn('RuntimeException');
$class->getInterfaces()->willReturn(array(
'Prophecy\Doubler\Generator\MirroredInterface', 'ArrayAccess', 'ArrayIterator'
));
$class->getProperties()->willReturn(array('name' => 'public', 'email' => 'private'));
$class->getMethods()->willReturn(array($method1, $method2, $method3));
$method1->getName()->willReturn('getName');
$method1->getVisibility()->willReturn('public');
$method1->returnsReference()->willReturn(false);
$method1->isStatic()->willReturn(true);
$method1->getArguments()->willReturn(array($argument11, $argument12));
$method1->hasReturnType()->willReturn(true);
$method1->getReturnType()->willReturn('string');
$method1->getCode()->willReturn('return $this->name;');
$method2->getName()->willReturn('getEmail');
$method2->getVisibility()->willReturn('protected');
$method2->returnsReference()->willReturn(false);
$method2->isStatic()->willReturn(false);
$method2->getArguments()->willReturn(array($argument21));
$method2->hasReturnType()->willReturn(false);
$method2->getCode()->willReturn('return $this->email;');
$method3->getName()->willReturn('getRefValue');
$method3->getVisibility()->willReturn('public');
$method3->returnsReference()->willReturn(true);
$method3->isStatic()->willReturn(false);
$method3->getArguments()->willReturn(array($argument31));
$method3->hasReturnType()->willReturn(false);
$method3->getCode()->willReturn('return $this->refValue;');
$argument11->getName()->willReturn('fullname');
$argument11->getTypeHint()->willReturn('array');
$argument11->isOptional()->willReturn(true);
$argument11->getDefault()->willReturn(null);
$argument11->isPassedByReference()->willReturn(false);
$argument11->isVariadic()->willReturn(false);
$argument12->getName()->willReturn('class');
$argument12->getTypeHint()->willReturn('ReflectionClass');
$argument12->isOptional()->willReturn(false);
$argument12->isPassedByReference()->willReturn(false);
$argument12->isVariadic()->willReturn(false);
$argument21->getName()->willReturn('default');
$argument21->getTypeHint()->willReturn('string');
$argument21->isOptional()->willReturn(true);
$argument21->getDefault()->willReturn('ever.zet@gmail.com');
$argument21->isPassedByReference()->willReturn(false);
$argument21->isVariadic()->willReturn(false);
$argument31->getName()->willReturn('refValue');
$argument31->getTypeHint()->willReturn(null);
$argument31->isOptional()->willReturn(false);
$argument31->getDefault()->willReturn();
$argument31->isPassedByReference()->willReturn(false);
$argument31->isVariadic()->willReturn(false);
$code = $this->generate('CustomClass', $class);
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$expected = <<<'PHP'
namespace {
class CustomClass extends \RuntimeException implements \Prophecy\Doubler\Generator\MirroredInterface, \ArrayAccess, \ArrayIterator {
public $name;
private $email;
public static function getName(array $fullname = NULL, \ReflectionClass $class): string {
return $this->name;
}
protected function getEmail(string $default = 'ever.zet@gmail.com') {
return $this->email;
}
public function &getRefValue( $refValue) {
return $this->refValue;
}
}
}
PHP;
} else {
$expected = <<<'PHP'
namespace {
class CustomClass extends \RuntimeException implements \Prophecy\Doubler\Generator\MirroredInterface, \ArrayAccess, \ArrayIterator {
public $name;
private $email;
public static function getName(array $fullname = NULL, \ReflectionClass $class) {
return $this->name;
}
protected function getEmail(\string $default = 'ever.zet@gmail.com') {
return $this->email;
}
public function &getRefValue( $refValue) {
return $this->refValue;
}
}
}
PHP;
}
$expected = strtr($expected, array("\r\n" => "\n", "\r" => "\n"));
$code->shouldBe($expected);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method1
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method2
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method3
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method4
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument1
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument2
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument3
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument4
*/
function it_generates_proper_php_code_for_variadics(
$class, $method1, $method2, $method3, $method4, $argument1, $argument2,
$argument3, $argument4
)
{
$class->getParentClass()->willReturn('stdClass');
$class->getInterfaces()->willReturn(array('Prophecy\Doubler\Generator\MirroredInterface'));
$class->getProperties()->willReturn(array());
$class->getMethods()->willReturn(array(
$method1, $method2, $method3, $method4
));
$method1->getName()->willReturn('variadic');
$method1->getVisibility()->willReturn('public');
$method1->returnsReference()->willReturn(false);
$method1->isStatic()->willReturn(false);
$method1->getArguments()->willReturn(array($argument1));
$method1->hasReturnType()->willReturn(false);
$method1->getCode()->willReturn('');
$method2->getName()->willReturn('variadicByRef');
$method2->getVisibility()->willReturn('public');
$method2->returnsReference()->willReturn(false);
$method2->isStatic()->willReturn(false);
$method2->getArguments()->willReturn(array($argument2));
$method2->hasReturnType()->willReturn(false);
$method2->getCode()->willReturn('');
$method3->getName()->willReturn('variadicWithType');
$method3->getVisibility()->willReturn('public');
$method3->returnsReference()->willReturn(false);
$method3->isStatic()->willReturn(false);
$method3->getArguments()->willReturn(array($argument3));
$method3->hasReturnType()->willReturn(false);
$method3->getCode()->willReturn('');
$method4->getName()->willReturn('variadicWithTypeByRef');
$method4->getVisibility()->willReturn('public');
$method4->returnsReference()->willReturn(false);
$method4->isStatic()->willReturn(false);
$method4->getArguments()->willReturn(array($argument4));
$method4->hasReturnType()->willReturn(false);
$method4->getCode()->willReturn('');
$argument1->getName()->willReturn('args');
$argument1->getTypeHint()->willReturn(null);
$argument1->isOptional()->willReturn(false);
$argument1->isPassedByReference()->willReturn(false);
$argument1->isVariadic()->willReturn(true);
$argument2->getName()->willReturn('args');
$argument2->getTypeHint()->willReturn(null);
$argument2->isOptional()->willReturn(false);
$argument2->isPassedByReference()->willReturn(true);
$argument2->isVariadic()->willReturn(true);
$argument3->getName()->willReturn('args');
$argument3->getTypeHint()->willReturn('\ReflectionClass');
$argument3->isOptional()->willReturn(false);
$argument3->isPassedByReference()->willReturn(false);
$argument3->isVariadic()->willReturn(true);
$argument4->getName()->willReturn('args');
$argument4->getTypeHint()->willReturn('\ReflectionClass');
$argument4->isOptional()->willReturn(false);
$argument4->isPassedByReference()->willReturn(true);
$argument4->isVariadic()->willReturn(true);
$code = $this->generate('CustomClass', $class);
$expected = <<<'PHP'
namespace {
class CustomClass extends \stdClass implements \Prophecy\Doubler\Generator\MirroredInterface {
public function variadic( ...$args) {
}
public function variadicByRef( &...$args) {
}
public function variadicWithType(\\ReflectionClass ...$args) {
}
public function variadicWithTypeByRef(\\ReflectionClass &...$args) {
}
}
}
PHP;
$expected = strtr($expected, array("\r\n" => "\n", "\r" => "\n"));
$code->shouldBe($expected);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument
*/
function it_overrides_properly_methods_with_args_passed_by_reference(
$class, $method, $argument
)
{
$class->getParentClass()->willReturn('RuntimeException');
$class->getInterfaces()->willReturn(array('Prophecy\Doubler\Generator\MirroredInterface'));
$class->getProperties()->willReturn(array());
$class->getMethods()->willReturn(array($method));
$method->getName()->willReturn('getName');
$method->getVisibility()->willReturn('public');
$method->isStatic()->willReturn(false);
$method->getArguments()->willReturn(array($argument));
$method->hasReturnType()->willReturn(false);
$method->returnsReference()->willReturn(false);
$method->getCode()->willReturn('return $this->name;');
$argument->getName()->willReturn('fullname');
$argument->getTypeHint()->willReturn('array');
$argument->isOptional()->willReturn(true);
$argument->getDefault()->willReturn(null);
$argument->isPassedByReference()->willReturn(true);
$argument->isVariadic()->willReturn(false);
$code = $this->generate('CustomClass', $class);
$expected =<<<'PHP'
namespace {
class CustomClass extends \RuntimeException implements \Prophecy\Doubler\Generator\MirroredInterface {
public function getName(array &$fullname = NULL) {
return $this->name;
}
}
}
PHP;
$expected = strtr($expected, array("\r\n" => "\n", "\r" => "\n"));
$code->shouldBe($expected);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
*/
function it_generates_empty_class_for_empty_ClassNode($class)
{
$class->getParentClass()->willReturn('stdClass');
$class->getInterfaces()->willReturn(array('Prophecy\Doubler\Generator\MirroredInterface'));
$class->getProperties()->willReturn(array());
$class->getMethods()->willReturn(array());
$code = $this->generate('CustomClass', $class);
$expected =<<<'PHP'
namespace {
class CustomClass extends \stdClass implements \Prophecy\Doubler\Generator\MirroredInterface {
}
}
PHP;
$expected = strtr($expected, array("\r\n" => "\n", "\r" => "\n"));
$code->shouldBe($expected);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
*/
function it_wraps_class_in_namespace_if_it_is_namespaced($class)
{
$class->getParentClass()->willReturn('stdClass');
$class->getInterfaces()->willReturn(array('Prophecy\Doubler\Generator\MirroredInterface'));
$class->getProperties()->willReturn(array());
$class->getMethods()->willReturn(array());
$code = $this->generate('My\Awesome\CustomClass', $class);
$expected =<<<'PHP'
namespace My\Awesome {
class CustomClass extends \stdClass implements \Prophecy\Doubler\Generator\MirroredInterface {
}
}
PHP;
$expected = strtr($expected, array("\r\n" => "\n", "\r" => "\n"));
$code->shouldBe($expected);
}
}

View File

@@ -1,44 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\Generator;
use PhpSpec\ObjectBehavior;
class ClassCreatorSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Doubler\Generator\ClassCodeGenerator $generator
*/
function let($generator)
{
$this->beConstructedWith($generator);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
*/
function it_evaluates_code_generated_by_ClassCodeGenerator($generator, $class)
{
$generator->generate('stdClass', $class)->shouldBeCalled()->willReturn(
'return 42;'
);
$this->create('stdClass', $class)->shouldReturn(42);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $class
*/
function it_throws_an_exception_if_class_does_not_exist_after_evaluation($generator, $class)
{
$generator->generate('CustomClass', $class)->shouldBeCalled()->willReturn(
'return 42;'
);
$class->getParentClass()->willReturn('stdClass');
$class->getInterfaces()->willReturn(array('Interface1', 'Interface2'));
$this->shouldThrow('Prophecy\Exception\Doubler\ClassCreatorException')
->duringCreate('CustomClass', $class);
}
}

View File

@@ -1,784 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\Generator;
use I\Simply;
use PhpSpec\ObjectBehavior;
use ReflectionClass;
use ReflectionMethod;
use ReflectionParameter;
class ClassMirrorSpec extends ObjectBehavior
{
/**
* @param ReflectionClass $class
* @param ReflectionClass $parent
* @param ReflectionMethod $method1
* @param ReflectionMethod $method2
* @param ReflectionMethod $method3
*/
function it_reflects_a_class_by_mirroring_all_its_public_methods(
$class, $parent, $method1, $method2, $method3
)
{
$class->getName()->willReturn('Custom\ClassName');
$class->getParentClass()->willReturn($parent);
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array(
$method1, $method2, $method3
));
$parent->getName()->willReturn('Custom\ParentClassName');
$method1->getDeclaringClass()->willReturn($class);
$method2->getDeclaringClass()->willReturn($class);
$method3->getDeclaringClass()->willReturn($class);
$method1->getName()->willReturn('getName');
$method2->getName()->willReturn('getSelf');
$method3->getName()->willReturn('getParent');
$method1->isFinal()->willReturn(false);
$method2->isFinal()->willReturn(false);
$method3->isFinal()->willReturn(false);
$method1->isProtected()->willReturn(false);
$method2->isProtected()->willReturn(false);
$method3->isProtected()->willReturn(false);
$method1->isStatic()->willReturn(false);
$method2->isStatic()->willReturn(false);
$method3->isStatic()->willReturn(false);
$method1->returnsReference()->willReturn(false);
$method2->returnsReference()->willReturn(false);
$method3->returnsReference()->willReturn(false);
$method1->getParameters()->willReturn(array());
$method2->getParameters()->willReturn(array());
$method3->getParameters()->willReturn(array());
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$method1->hasReturnType()->willReturn(true);
$method1->getReturnType()->willReturn('string');
$method2->hasReturnType()->willReturn(true);
$method2->getReturnType()->willReturn('self');
$method3->hasReturnType()->willReturn(true);
$method3->getReturnType()->willReturn('parent');
}
$classNode = $this->reflect($class, array());
$classNode->shouldBeAnInstanceOf('Prophecy\Doubler\Generator\Node\ClassNode');
$classNode->getParentClass()->shouldReturn('Custom\ClassName');
$methodNodes = $classNode->getMethods();
$methodNodes->shouldHaveCount(3);
$classNode->hasMethod('getName')->shouldReturn(true);
$classNode->hasMethod('getSelf')->shouldReturn(true);
$classNode->hasMethod('getParent')->shouldReturn(true);
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$classNode->getMethod('getName')->getReturnType()->shouldReturn('string');
$classNode->getMethod('getSelf')->getReturnType()->shouldReturn('\Custom\ClassName');
$classNode->getMethod('getParent')->getReturnType()->shouldReturn('\Custom\ParentClassName');
}
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
* @param ReflectionParameter $parameter
*/
function it_changes_argument_names_if_they_are_varying($class, $method, $parameter)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$method->getParameters()->willReturn(array($parameter));
$method->getName()->willReturn('methodName');
$method->isFinal()->willReturn(false);
$method->isProtected()->willReturn(false);
$method->isStatic()->willReturn(false);
$method->returnsReference()->willReturn(false);
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$method->hasReturnType()->willReturn(false);
}
$parameter->getName()->willReturn('...');
$parameter->isDefaultValueAvailable()->willReturn(true);
$parameter->getDefaultValue()->willReturn(null);
$parameter->isPassedByReference()->willReturn(false);
$parameter->getClass()->willReturn($class);
if (version_compare(PHP_VERSION, '5.6', '>=')) {
$parameter->isVariadic()->willReturn(false);
}
$classNode = $this->reflect($class, array());
$methodNodes = $classNode->getMethods();
$argumentNodes = $methodNodes['methodName']->getArguments();
$argumentNode = $argumentNodes[0];
$argumentNode->getName()->shouldReturn('__dot_dot_dot__');
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
*/
function it_reflects_protected_abstract_methods($class, $method)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array($method));
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array());
$method->isProtected()->willReturn(true);
$method->isStatic()->willReturn(false);
$method->getParameters()->willReturn(array());
$method->getName()->willReturn('innerDetail');
$method->returnsReference()->willReturn(false);
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$method->hasReturnType()->willReturn(false);
}
$classNode = $this->reflect($class, array());
$classNode->shouldBeAnInstanceOf('Prophecy\Doubler\Generator\Node\ClassNode');
$classNode->getParentClass()->shouldReturn('Custom\ClassName');
$methodNodes = $classNode->getMethods();
$methodNodes->shouldHaveCount(1);
$methodNodes['innerDetail']->getVisibility()->shouldReturn('protected');
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
*/
function it_reflects_public_static_methods($class, $method)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array($method));
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array());
$method->isProtected()->willReturn(true);
$method->isStatic()->willReturn(true);
$method->getParameters()->willReturn(array());
$method->getName()->willReturn('innerDetail');
$method->returnsReference()->willReturn(false);
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$method->hasReturnType()->willReturn(false);
}
$classNode = $this->reflect($class, array());
$classNode->shouldBeAnInstanceOf('Prophecy\Doubler\Generator\Node\ClassNode');
$classNode->getParentClass()->shouldReturn('Custom\ClassName');
$methodNodes = $classNode->getMethods();
$methodNodes->shouldHaveCount(1);
$methodNodes['innerDetail']->getVisibility()->shouldReturn('protected');
$methodNodes['innerDetail']->isStatic()->shouldReturn(true);
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $constructMethod
* @param ReflectionMethod $destructMethod
* @param ReflectionMethod $sleepMethod
* @param ReflectionMethod $wakeupMethod
* @param ReflectionMethod $toStringMethod
* @param ReflectionMethod $callMethod
* @param ReflectionMethod $invokeMethod
*/
function it_reflects_allowed_magic_methods($class, $constructMethod, $destructMethod, $sleepMethod, $wakeupMethod, $toStringMethod, $callMethod, $invokeMethod)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array(
$constructMethod, $destructMethod, $sleepMethod, $wakeupMethod, $toStringMethod, $callMethod, $invokeMethod
));
$constructMethod->getName()->willReturn('__construct');
$destructMethod->getName()->willReturn('__destruct');
$sleepMethod->getName()->willReturn('__sleep');
$wakeupMethod->getName()->willReturn('__wakeup');
$toStringMethod->getName()->willReturn('__toString');
$callMethod->getName()->willReturn('__call');
$invokeMethod->getName()->willReturn('__invoke');
$constructMethod->isFinal()->willReturn(false);
$destructMethod->isFinal()->willReturn(false);
$sleepMethod->isFinal()->willReturn(false);
$wakeupMethod->isFinal()->willReturn(false);
$toStringMethod->isFinal()->willReturn(false);
$callMethod->isFinal()->willReturn(false);
$invokeMethod->isFinal()->willReturn(false);
$constructMethod->isProtected()->willReturn(false);
$destructMethod->isProtected()->willReturn(false);
$sleepMethod->isProtected()->willReturn(false);
$wakeupMethod->isProtected()->willReturn(false);
$toStringMethod->isProtected()->willReturn(false);
$callMethod->isProtected()->willReturn(false);
$invokeMethod->isProtected()->willReturn(false);
$constructMethod->isStatic()->willReturn(false);
$destructMethod->isStatic()->willReturn(false);
$sleepMethod->isStatic()->willReturn(false);
$wakeupMethod->isStatic()->willReturn(false);
$toStringMethod->isStatic()->willReturn(false);
$callMethod->isStatic()->willReturn(false);
$invokeMethod->isStatic()->willReturn(false);
$constructMethod->returnsReference()->willReturn(false);
$destructMethod->returnsReference()->willReturn(false);
$sleepMethod->returnsReference()->willReturn(false);
$wakeupMethod->returnsReference()->willReturn(false);
$toStringMethod->returnsReference()->willReturn(false);
$callMethod->returnsReference()->willReturn(false);
$invokeMethod->returnsReference()->willReturn(false);
$constructMethod->getParameters()->willReturn(array());
$destructMethod->getParameters()->willReturn(array());
$sleepMethod->getParameters()->willReturn(array());
$wakeupMethod->getParameters()->willReturn(array());
$toStringMethod->getParameters()->willReturn(array());
$callMethod->getParameters()->willReturn(array());
$invokeMethod->getParameters()->willReturn(array());
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$constructMethod->hasReturnType()->willReturn(false);
$destructMethod->hasReturnType()->willReturn(false);
$sleepMethod->hasReturnType()->willReturn(false);
$wakeupMethod->hasReturnType()->willReturn(false);
$toStringMethod->hasReturnType()->willReturn(false);
$callMethod->hasReturnType()->willReturn(false);
$invokeMethod->hasReturnType()->willReturn(false);
}
$classNode = $this->reflect($class, array());
$classNode->shouldBeAnInstanceOf('Prophecy\Doubler\Generator\Node\ClassNode');
$classNode->getParentClass()->shouldReturn('Custom\ClassName');
$methodNodes = $classNode->getMethods();
$methodNodes->shouldHaveCount(7);
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
* @param ReflectionParameter $param1
* @param ReflectionParameter $param2
* @param ReflectionClass $typeHint
* @param ReflectionParameter $param3
* @param ReflectionParameter $param4
*/
function it_properly_reads_methods_arguments_with_types(
$class, $method, $param1, $param2, $typeHint, $param3, $param4
)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
$method->getName()->willReturn('methodWithArgs');
$method->isFinal()->willReturn(false);
$method->isProtected()->willReturn(true);
$method->isStatic()->willReturn(false);
$method->returnsReference()->willReturn(false);
$method->getParameters()->willReturn(array($param1, $param2, $param3, $param4));
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$method->hasReturnType()->willReturn(false);
}
$param1->getName()->willReturn('arg_1');
$param1->isArray()->willReturn(true);
$param1->getClass()->willReturn(null);
$param1->isDefaultValueAvailable()->willReturn(true);
$param1->isPassedByReference()->willReturn(false);
$param1->allowsNull()->willReturn(false);
$param1->getDefaultValue()->willReturn(array());
$param2->getName()->willReturn('arg2');
$param2->isArray()->willReturn(false);
$param2->getClass()->willReturn($typeHint);
$param2->isDefaultValueAvailable()->willReturn(false);
$param2->isOptional()->willReturn(false);
$param2->isPassedByReference()->willReturn(false);
$param2->allowsNull()->willReturn(false);
$typeHint->getName()->willReturn('ArrayAccess');
$param3->getName()->willReturn('arg_3');
$param3->isArray()->willReturn(false);
if (version_compare(PHP_VERSION, '5.4', '>=')) {
$param3->isCallable()->willReturn(true);
}
$param3->getClass()->willReturn(null);
$param3->isOptional()->willReturn(false);
$param3->isDefaultValueAvailable()->willReturn(false);
$param3->isPassedByReference()->willReturn(false);
$param3->allowsNull()->willReturn(true);
$param4->getName()->willReturn('arg_4');
$param4->isArray()->willReturn(false);
$param4->getClass()->willReturn($typeHint);
$param4->isPassedByReference()->willReturn(false);
$param4->allowsNull()->willReturn(true);
if (version_compare(PHP_VERSION, '5.6', '>=')) {
$param1->isVariadic()->willReturn(false);
$param2->isVariadic()->willReturn(false);
$param3->isVariadic()->willReturn(false);
$param4->isVariadic()->willReturn(true);
} else {
$param4->isOptional()->willReturn(true);
$param4->isDefaultValueAvailable()->willReturn(false);
}
$classNode = $this->reflect($class, array());
$methodNodes = $classNode->getMethods();
$argNodes = $methodNodes['methodWithArgs']->getArguments();
$argNodes[0]->getName()->shouldReturn('arg_1');
$argNodes[0]->getTypeHint()->shouldReturn('array');
$argNodes[0]->isOptional()->shouldReturn(true);
$argNodes[0]->getDefault()->shouldReturn(array());
$argNodes[1]->getName()->shouldReturn('arg2');
$argNodes[1]->getTypeHint()->shouldReturn('ArrayAccess');
$argNodes[1]->isOptional()->shouldReturn(false);
$argNodes[2]->getName()->shouldReturn('arg_3');
if (version_compare(PHP_VERSION, '5.4', '>=')) {
$argNodes[2]->getTypeHint()->shouldReturn('callable');
$argNodes[2]->isOptional()->shouldReturn(true);
$argNodes[2]->getDefault()->shouldReturn(null);
} else {
$argNodes[2]->isOptional()->shouldReturn(false);
}
$argNodes[3]->getName()->shouldReturn('arg_4');
$argNodes[3]->getTypeHint()->shouldReturn('ArrayAccess');
if (version_compare(PHP_VERSION, '5.6', '>=')) {
$argNodes[3]->isVariadic()->shouldReturn(true);
} else {
$argNodes[3]->isOptional()->shouldReturn(true);
$argNodes[3]->getDefault()->shouldReturn(null);
}
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
* @param ReflectionParameter $param1
*/
function it_marks_required_args_without_types_as_not_optional(
$class, $method, $param1
)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
$method->getName()->willReturn('methodWithArgs');
$method->isFinal()->willReturn(false);
$method->isProtected()->willReturn(false);
$method->isStatic()->willReturn(false);
$method->returnsReference()->willReturn(false);
$method->getParameters()->willReturn(array($param1));
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$method->hasReturnType()->willReturn(false);
}
$param1->getName()->willReturn('arg_1');
$param1->isArray()->willReturn(false);
if (version_compare(PHP_VERSION, '5.4', '>=')) {
$param1->isCallable()->willReturn(false);
}
$param1->getClass()->willReturn(null);
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$param1->hasType()->willReturn(false);
}
if (version_compare(PHP_VERSION, '5.6', '>=')) {
$param1->isVariadic()->willReturn(false);
}
$param1->isDefaultValueAvailable()->willReturn(false);
$param1->isOptional()->willReturn(false);
$param1->isPassedByReference()->willReturn(false);
$param1->allowsNull()->willReturn(true);
if (defined('HHVM_VERSION')) {
$param1->getTypehintText()->willReturn(null);
}
$classNode = $this->reflect($class, array());
$methodNodes = $classNode->getMethods();
$argNodes = $methodNodes['methodWithArgs']->getArguments();
$argNodes[0]->isOptional()->shouldReturn(false);
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
* @param ReflectionParameter $param1
* @param ReflectionParameter $param2
* @param ReflectionParameter $param3
* @param ReflectionClass $typeHint
*/
function it_marks_passed_by_reference_args_as_passed_by_reference(
$class, $method, $param1, $param2, $param3, $typeHint
)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
$method->getName()->willReturn('methodWithArgs');
$method->isFinal()->willReturn(false);
$method->isProtected()->willReturn(false);
$method->isStatic()->willReturn(false);
$method->returnsReference()->willReturn(false);
$method->getParameters()->willReturn(array($param1, $param2, $param3));
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$method->hasReturnType()->willReturn(false);
}
$param1->getName()->willReturn('arg_1');
$param1->isArray()->willReturn(false);
if (version_compare(PHP_VERSION, '5.4', '>=')) {
$param1->isCallable()->willReturn(false);
}
$param1->getClass()->willReturn(null);
if (version_compare(PHP_VERSION, '5.6', '>=')) {
$param1->isVariadic()->willReturn(false);
}
$param1->isDefaultValueAvailable()->willReturn(false);
$param1->isOptional()->willReturn(true);
$param1->isPassedByReference()->willReturn(true);
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$param1->hasType()->willReturn(false);
}
$param1->allowsNull()->willReturn(false);
if (defined('HHVM_VERSION')) {
$param1->getTypehintText()->willReturn(null);
}
$param2->getName()->willReturn('arg2');
$param2->isArray()->willReturn(false);
$param2->getClass()->willReturn($typeHint);
if (version_compare(PHP_VERSION, '5.6', '>=')) {
$param2->isVariadic()->willReturn(false);
}
$param2->isDefaultValueAvailable()->willReturn(false);
$param2->isOptional()->willReturn(false);
$param2->isPassedByReference()->willReturn(false);
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$param2->hasType()->willReturn(false);
}
$param2->allowsNull()->willReturn(false);
$typeHint->getName()->willReturn('ArrayAccess');
$param3->getName()->willReturn('arg2');
$param3->isArray()->willReturn(false);
$param3->getClass()->willReturn($typeHint);
if (version_compare(PHP_VERSION, '5.6', '>=')) {
$param3->isVariadic()->willReturn(true);
} else {
$param3->isOptional()->willReturn(true);
$param3->isDefaultValueAvailable()->willReturn(false);
}
$param3->isPassedByReference()->willReturn(true);
$param3->allowsNull()->willReturn(true);
$classNode = $this->reflect($class, array());
$methodNodes = $classNode->getMethods();
$argNodes = $methodNodes['methodWithArgs']->getArguments();
$argNodes[0]->isPassedByReference()->shouldReturn(true);
$argNodes[1]->isPassedByReference()->shouldReturn(false);
$argNodes[2]->isPassedByReference()->shouldReturn(true);
}
/**
* @param ReflectionClass $class
*/
function it_throws_an_exception_if_class_is_final($class)
{
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(true);
$class->getName()->willReturn('Custom\ClassName');
$this->shouldThrow('Prophecy\Exception\Doubler\ClassMirrorException')
->duringReflect($class, array());
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
*/
function it_ignores_final_methods($class, $method)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
$method->isFinal()->willReturn(true);
$method->getName()->willReturn('finalImplementation');
$classNode = $this->reflect($class, array());
$classNode->getMethods()->shouldHaveCount(0);
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
*/
function it_marks_final_methods_as_unextendable($class, $method)
{
$class->getName()->willReturn('Custom\ClassName');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
$method->isFinal()->willReturn(true);
$method->getName()->willReturn('finalImplementation');
$classNode = $this->reflect($class, array());
$classNode->getUnextendableMethods()->shouldHaveCount(1);
$classNode->isExtendable('finalImplementation')->shouldReturn(false);
}
/**
* @param ReflectionClass $interface
*/
function it_throws_an_exception_if_interface_provided_instead_of_class($interface)
{
$interface->isInterface()->willReturn(true);
$interface->getName()->willReturn('Custom\ClassName');
$this->shouldThrow('Prophecy\Exception\InvalidArgumentException')
->duringReflect($interface, array());
}
/**
* @param ReflectionClass $interface1
* @param ReflectionClass $interface2
* @param ReflectionMethod $method1
* @param ReflectionMethod $method2
* @param ReflectionMethod $method3
*/
function it_reflects_all_interfaces_methods(
$interface1, $interface2, $method1, $method2, $method3
)
{
$interface1->getName()->willReturn('MyInterface1');
$interface2->getName()->willReturn('MyInterface2');
$interface1->isInterface()->willReturn(true);
$interface2->isInterface()->willReturn(true);
$interface1->getMethods()->willReturn(array($method1));
$interface2->getMethods()->willReturn(array($method2, $method3));
$method1->getName()->willReturn('getName');
$method2->getName()->willReturn('isPublic');
$method3->getName()->willReturn('isAbstract');
$method1->isProtected()->willReturn(false);
$method2->isProtected()->willReturn(false);
$method3->isProtected()->willReturn(false);
$method1->returnsReference()->willReturn(false);
$method2->returnsReference()->willReturn(false);
$method3->returnsReference()->willReturn(false);
$method1->isStatic()->willReturn(false);
$method2->isStatic()->willReturn(false);
$method3->isStatic()->willReturn(false);
$method1->getParameters()->willReturn(array());
$method2->getParameters()->willReturn(array());
$method3->getParameters()->willReturn(array());
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$method1->hasReturnType()->willReturn(false);
$method2->hasReturnType()->willReturn(false);
$method3->hasReturnType()->willReturn(false);
}
$classNode = $this->reflect(null, array($interface1, $interface2));
$classNode->shouldBeAnInstanceOf('Prophecy\Doubler\Generator\Node\ClassNode');
$classNode->getParentClass()->shouldReturn('stdClass');
$classNode->getInterfaces()->shouldReturn(array(
'Prophecy\Doubler\Generator\ReflectionInterface', 'MyInterface2', 'MyInterface1',
));
$methodNodes = $classNode->getMethods();
$methodNodes->shouldHaveCount(3);
$classNode->hasMethod('getName')->shouldReturn(true);
$classNode->hasMethod('isPublic')->shouldReturn(true);
$classNode->hasMethod('isAbstract')->shouldReturn(true);
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method1
* @param ReflectionMethod $method2
* @param ReflectionMethod $method3
*/
function it_ignores_virtually_private_methods($class, $method1, $method2, $method3)
{
$class->getName()->willReturn('SomeClass');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method1, $method2, $method3));
$method1->getName()->willReturn('_getName');
$method2->getName()->willReturn('__toString');
$method3->getName()->willReturn('isAbstract');
$method1->isFinal()->willReturn(false);
$method2->isFinal()->willReturn(false);
$method3->isFinal()->willReturn(false);
$method1->isProtected()->willReturn(false);
$method2->isProtected()->willReturn(false);
$method3->isProtected()->willReturn(false);
$method1->isStatic()->willReturn(false);
$method2->isStatic()->willReturn(false);
$method3->isStatic()->willReturn(false);
$method1->returnsReference()->willReturn(false);
$method2->returnsReference()->willReturn(false);
$method3->returnsReference()->willReturn(false);
$method1->getParameters()->willReturn(array());
$method2->getParameters()->willReturn(array());
$method3->getParameters()->willReturn(array());
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$method1->hasReturnType()->willReturn(false);
$method2->hasReturnType()->willReturn(false);
$method3->hasReturnType()->willReturn(false);
}
$classNode = $this->reflect($class, array());
$methodNodes = $classNode->getMethods();
$methodNodes->shouldHaveCount(2);
$classNode->hasMethod('isAbstract')->shouldReturn(true);
}
/**
* @param ReflectionClass $class
* @param ReflectionMethod $method
*/
function it_does_not_throw_exception_for_virtually_private_finals($class, $method)
{
$class->getName()->willReturn('SomeClass');
$class->isInterface()->willReturn(false);
$class->isFinal()->willReturn(false);
$class->getMethods(ReflectionMethod::IS_ABSTRACT)->willReturn(array());
$class->getMethods(ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
$method->getName()->willReturn('__toString');
$method->isFinal()->willReturn(true);
$this->shouldNotThrow()->duringReflect($class, array());
}
/**
* @param ReflectionClass $class
*/
function it_throws_an_exception_if_class_provided_in_interfaces_list($class)
{
$class->getName()->willReturn('MyClass');
$class->isInterface()->willReturn(false);
$this->shouldThrow('InvalidArgumentException')
->duringReflect(null, array($class));
}
function it_throws_an_exception_if_not_reflection_provided_as_interface()
{
$this->shouldThrow('InvalidArgumentException')
->duringReflect(null, array(null));
}
function it_doesnt_fail_to_typehint_nonexistent_FQCN()
{
$classNode = $this->reflect(new ReflectionClass('spec\Prophecy\Doubler\Generator\OptionalDepsClass'), array());
$method = $classNode->getMethod('iHaveAStrangeTypeHintedArg');
$arguments = $method->getArguments();
$arguments[0]->getTypeHint()->shouldBe('I\Simply\Am\Nonexistent');
}
function it_doesnt_fail_to_typehint_nonexistent_RQCN()
{
$classNode = $this->reflect(new ReflectionClass('spec\Prophecy\Doubler\Generator\OptionalDepsClass'), array());
$method = $classNode->getMethod('iHaveAnEvenStrangerTypeHintedArg');
$arguments = $method->getArguments();
$arguments[0]->getTypeHint()->shouldBe('I\Simply\Am\Not');
}
function it_doesnt_use_scalar_typehints()
{
$classNode = $this->reflect(new ReflectionClass('ReflectionMethod'), array());
$method = $classNode->getMethod('export');
$arguments = $method->getArguments();
$arguments[0]->getTypeHint()->shouldReturn(null);
$arguments[1]->getTypeHint()->shouldReturn(null);
$arguments[2]->getTypeHint()->shouldReturn(null);
}
}
class OptionalDepsClass
{
public function iHaveAStrangeTypeHintedArg(\I\Simply\Am\Nonexistent $class)
{
}
public function iHaveAnEvenStrangerTypeHintedArg(Simply\Am\Not $class)
{
}
}

View File

@@ -1,92 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\Generator\Node;
use PhpSpec\ObjectBehavior;
class ArgumentNodeSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('name');
}
function it_is_not_be_passed_by_reference_by_default()
{
$this->shouldNotBePassedByReference();
}
function it_is_passed_by_reference_if_marked()
{
$this->setAsPassedByReference();
$this->shouldBePassedByReference();
}
function it_is_not_variadic_by_default()
{
$this->shouldNotBeVariadic();
}
function it_is_variadic_if_marked()
{
$this->setAsVariadic();
$this->shouldBeVariadic();
}
function it_does_not_have_default_by_default()
{
$this->shouldNotHaveDefault();
}
function it_does_not_have_default_if_variadic()
{
$this->setDefault(null);
$this->setAsVariadic();
$this->shouldNotHaveDefault();
}
function it_does_have_default_if_not_variadic()
{
$this->setDefault(null);
$this->setAsVariadic(false);
$this->hasDefault()->shouldReturn(true);
}
function it_has_name_with_which_it_was_been_constructed()
{
$this->getName()->shouldReturn('name');
}
function it_has_no_typehint_by_default()
{
$this->getTypeHint()->shouldReturn(null);
}
function its_typeHint_is_mutable()
{
$this->setTypeHint('array');
$this->getTypeHint()->shouldReturn('array');
}
function it_does_not_have_default_value_by_default()
{
$this->getDefault()->shouldReturn(null);
}
function it_is_not_optional_by_default()
{
$this->isOptional()->shouldReturn(false);
}
function its_default_is_mutable()
{
$this->setDefault(array());
$this->getDefault()->shouldReturn(array());
}
function it_is_marked_as_optional_when_default_is_set()
{
$this->setDefault(null);
$this->isOptional()->shouldReturn(true);
}
}

View File

@@ -1,200 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\Generator\Node;
use PhpSpec\ObjectBehavior;
use Prophecy\Exception\Doubler\MethodNotExtendableException;
class ClassNodeSpec extends ObjectBehavior
{
function its_parentClass_is_a_stdClass_by_default()
{
$this->getParentClass()->shouldReturn('stdClass');
}
function its_parentClass_is_mutable()
{
$this->setParentClass('Exception');
$this->getParentClass()->shouldReturn('Exception');
}
function its_parentClass_is_set_to_stdClass_if_user_set_null()
{
$this->setParentClass(null);
$this->getParentClass()->shouldReturn('stdClass');
}
function it_does_not_implement_any_interface_by_default()
{
$this->getInterfaces()->shouldHaveCount(0);
}
function its_addInterface_adds_item_to_the_list_of_implemented_interfaces()
{
$this->addInterface('MyInterface');
$this->getInterfaces()->shouldHaveCount(1);
}
function its_hasInterface_returns_true_if_class_implements_interface()
{
$this->addInterface('MyInterface');
$this->hasInterface('MyInterface')->shouldReturn(true);
}
function its_hasInterface_returns_false_if_class_does_not_implements_interface()
{
$this->hasInterface('MyInterface')->shouldReturn(false);
}
function it_supports_implementation_of_multiple_interfaces()
{
$this->addInterface('MyInterface');
$this->addInterface('MySecondInterface');
$this->getInterfaces()->shouldHaveCount(2);
}
function it_ignores_same_interfaces_added_twice()
{
$this->addInterface('MyInterface');
$this->addInterface('MyInterface');
$this->getInterfaces()->shouldHaveCount(1);
$this->getInterfaces()->shouldReturn(array('MyInterface'));
}
function it_does_not_have_methods_by_default()
{
$this->getMethods()->shouldHaveCount(0);
}
/**
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method1
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method2
*/
function it_can_has_methods($method1, $method2)
{
$method1->getName()->willReturn('__construct');
$method2->getName()->willReturn('getName');
$this->addMethod($method1);
$this->addMethod($method2);
$this->getMethods()->shouldReturn(array(
'__construct' => $method1,
'getName' => $method2
));
}
/**
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
*/
function its_hasMethod_returns_true_if_method_exists($method)
{
$method->getName()->willReturn('getName');
$this->addMethod($method);
$this->hasMethod('getName')->shouldReturn(true);
}
/**
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
*/
function its_getMethod_returns_method_by_name($method)
{
$method->getName()->willReturn('getName');
$this->addMethod($method);
$this->getMethod('getName')->shouldReturn($method);
}
function its_hasMethod_returns_false_if_method_does_not_exists()
{
$this->hasMethod('getName')->shouldReturn(false);
}
/**
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
*/
function its_hasMethod_returns_false_if_method_has_been_removed($method)
{
$method->getName()->willReturn('getName');
$this->addMethod($method);
$this->removeMethod('getName');
$this->hasMethod('getName')->shouldReturn(false);
}
function it_does_not_have_properties_by_default()
{
$this->getProperties()->shouldHaveCount(0);
}
function it_is_able_to_have_properties()
{
$this->addProperty('title');
$this->addProperty('text', 'private');
$this->getProperties()->shouldReturn(array(
'title' => 'public',
'text' => 'private'
));
}
function its_addProperty_does_not_accept_unsupported_visibility()
{
$this->shouldThrow('InvalidArgumentException')->duringAddProperty('title', 'town');
}
function its_addProperty_lowercases_visibility_before_setting()
{
$this->addProperty('text', 'PRIVATE');
$this->getProperties()->shouldReturn(array('text' => 'private'));
}
function its_has_no_unextendable_methods_by_default()
{
$this->getUnextendableMethods()->shouldHaveCount(0);
}
function its_addUnextendableMethods_adds_an_unextendable_method()
{
$this->addUnextendableMethod('testMethod');
$this->getUnextendableMethods()->shouldHaveCount(1);
}
function its_methods_are_extendable_by_default()
{
$this->isExtendable('testMethod')->shouldReturn(true);
}
function its_unextendable_methods_are_not_extendable()
{
$this->addUnextendableMethod('testMethod');
$this->isExtendable('testMethod')->shouldReturn(false);
}
function its_addUnextendableMethods_doesnt_create_duplicates()
{
$this->addUnextendableMethod('testMethod');
$this->addUnextendableMethod('testMethod');
$this->getUnextendableMethods()->shouldHaveCount(1);
}
/**
* @param \Prophecy\Doubler\Generator\Node\MethodNode $method
*/
function it_throws_an_exception_when_adding_a_method_that_isnt_extendable($method)
{
$this->addUnextendableMethod('testMethod');
$method->getName()->willReturn('testMethod');
$expectedException = new MethodNotExtendableException(
"Method `testMethod` is not extendable, so can not be added.",
"stdClass",
"testMethod"
);
$this->shouldThrow($expectedException)->duringAddMethod($method);
}
}

View File

@@ -1,141 +0,0 @@
<?php
namespace spec\Prophecy\Doubler\Generator\Node;
use PhpSpec\ObjectBehavior;
class MethodNodeSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('getTitle');
}
function it_has_a_name()
{
$this->getName()->shouldReturn('getTitle');
}
function it_has_public_visibility_by_default()
{
$this->getVisibility()->shouldReturn('public');
}
function its_visibility_is_mutable()
{
$this->setVisibility('private');
$this->getVisibility()->shouldReturn('private');
}
function it_is_not_static_by_default()
{
$this->shouldNotBeStatic();
}
function it_does_not_return_a_reference_by_default()
{
$this->returnsReference()->shouldReturn(false);
}
function it_should_be_settable_as_returning_a_reference_through_setter()
{
$this->setReturnsReference();
$this->returnsReference()->shouldReturn(true);
}
function it_should_be_settable_as_static_through_setter()
{
$this->setStatic();
$this->shouldBeStatic();
}
function it_accepts_only_supported_visibilities()
{
$this->shouldThrow('InvalidArgumentException')->duringSetVisibility('stealth');
}
function it_lowercases_visibility_before_setting_it()
{
$this->setVisibility('Public');
$this->getVisibility()->shouldReturn('public');
}
/**
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument1
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument2
*/
function its_useParentCode_causes_method_to_call_parent($argument1, $argument2)
{
$argument1->getName()->willReturn('objectName');
$argument2->getName()->willReturn('default');
$argument1->isVariadic()->willReturn(false);
$argument2->isVariadic()->willReturn(true);
$this->addArgument($argument1);
$this->addArgument($argument2);
$this->useParentCode();
$this->getCode()->shouldReturn(
'return parent::getTitle($objectName, ...$default);'
);
}
function its_code_is_mutable()
{
$this->setCode('echo "code";');
$this->getCode()->shouldReturn('echo "code";');
}
function its_reference_returning_methods_will_generate_exceptions()
{
$this->setCode('echo "code";');
$this->setReturnsReference();
$this->getCode()->shouldReturn("throw new \Prophecy\Exception\Doubler\ReturnByReferenceException('Returning by reference not supported', get_class(\$this), 'getTitle');");
}
function its_setCode_provided_with_null_cleans_method_body()
{
$this->setCode(null);
$this->getCode()->shouldReturn('');
}
function it_is_constructable_with_code()
{
$this->beConstructedWith('getTitle', 'die();');
$this->getCode()->shouldReturn('die();');
}
function it_does_not_have_arguments_by_default()
{
$this->getArguments()->shouldHaveCount(0);
}
/**
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument1
* @param \Prophecy\Doubler\Generator\Node\ArgumentNode $argument2
*/
function it_supports_adding_arguments($argument1, $argument2)
{
$this->addArgument($argument1);
$this->addArgument($argument2);
$this->getArguments()->shouldReturn(array($argument1, $argument2));
}
function it_does_not_have_return_type_by_default()
{
$this->hasReturnType()->shouldReturn(false);
}
function it_setReturnType_sets_return_type()
{
$returnType = 'string';
$this->setReturnType($returnType);
$this->hasReturnType()->shouldReturn(true);
$this->getReturnType()->shouldReturn($returnType);
}
}

View File

@@ -1,96 +0,0 @@
<?php
namespace spec\Prophecy\Doubler;
use PhpSpec\ObjectBehavior;
class LazyDoubleSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Doubler\Doubler $doubler
*/
function let($doubler)
{
$this->beConstructedWith($doubler);
}
/**
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double
*/
function it_returns_anonymous_double_instance_by_default($doubler, $double)
{
$doubler->double(null, array())->willReturn($double);
$this->getInstance()->shouldReturn($double);
}
/**
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double
* @param \ReflectionClass $class
*/
function it_returns_class_double_instance_if_set($doubler, $double, $class)
{
$doubler->double($class, array())->willReturn($double);
$this->setParentClass($class);
$this->getInstance()->shouldReturn($double);
}
/**
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double1
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double2
*/
function it_returns_same_double_instance_if_called_2_times(
$doubler, $double1, $double2
)
{
$doubler->double(null, array())->willReturn($double1);
$doubler->double(null, array())->willReturn($double2);
$this->getInstance()->shouldReturn($double2);
$this->getInstance()->shouldReturn($double2);
}
function its_setParentClass_throws_ClassNotFoundException_if_class_not_found()
{
$this->shouldThrow('Prophecy\Exception\Doubler\ClassNotFoundException')
->duringSetParentClass('SomeUnexistingClass');
}
/**
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double
*/
function its_setParentClass_throws_exception_if_prophecy_is_already_created(
$doubler, $double
)
{
$doubler->double(null, array())->willReturn($double);
$this->getInstance();
$this->shouldThrow('Prophecy\Exception\Doubler\DoubleException')
->duringSetParentClass('stdClass');
}
function its_addInterface_throws_InterfaceNotFoundException_if_no_interface_found()
{
$this->shouldThrow('Prophecy\Exception\Doubler\InterfaceNotFoundException')
->duringAddInterface('SomeUnexistingInterface');
}
/**
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double
*/
function its_addInterface_throws_exception_if_prophecy_is_already_created(
$doubler, $double
)
{
$doubler->double(null, array())->willReturn($double);
$this->getInstance();
$this->shouldThrow('Prophecy\Exception\Doubler\DoubleException')
->duringAddInterface('ArrayAccess');
}
}

View File

@@ -1,72 +0,0 @@
<?php
namespace spec\Prophecy\Doubler;
use PhpSpec\ObjectBehavior;
class NameGeneratorSpec extends ObjectBehavior
{
/**
* @param \ReflectionClass $class
*/
function its_name_generates_name_based_on_simple_class_reflection($class)
{
$class->getName()->willReturn('stdClass');
$this->name($class, array())->shouldStartWith('Double\stdClass\\');
}
/**
* @param \ReflectionClass $class
*/
function its_name_generates_name_based_on_namespaced_class_reflection($class)
{
$class->getName()->willReturn('Some\Custom\Class');
$this->name($class, array())->shouldStartWith('Double\Some\Custom\Class\P');
}
/**
* @param \ReflectionClass $interface1
* @param \ReflectionClass $interface2
*/
function its_name_generates_name_based_on_interface_shortnames($interface1, $interface2)
{
$interface1->getShortName()->willReturn('HandlerInterface');
$interface2->getShortName()->willReturn('LoaderInterface');
$this->name(null, array($interface1, $interface2))->shouldStartWith(
'Double\HandlerInterface\LoaderInterface\P'
);
}
function it_generates_proper_name_for_no_class_and_interfaces_list()
{
$this->name(null, array())->shouldStartWith('Double\stdClass\P');
}
/**
* @param \ReflectionClass $class
* @param \ReflectionClass $interface1
* @param \ReflectionClass $interface2
*/
function its_name_generates_name_based_only_on_class_if_its_available(
$class, $interface1, $interface2
)
{
$class->getName()->willReturn('Some\Custom\Class');
$interface1->getShortName()->willReturn('HandlerInterface');
$interface2->getShortName()->willReturn('LoaderInterface');
$this->name($class, array($interface1, $interface2))->shouldStartWith(
'Double\Some\Custom\Class\P'
);
}
public function getMatchers()
{
return array(
'startWith' => function ($subject, $string) {
return 0 === strpos($subject, $string);
},
);
}
}

View File

@@ -1,32 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Call;
use PhpSpec\ObjectBehavior;
use spec\Prophecy\Exception\Prophecy\Prophecy;
class UnexpectedCallExceptionSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Prophecy\ObjectProphecy $objectProphecy
*/
function let($objectProphecy)
{
$this->beConstructedWith('msg', $objectProphecy, 'getName', array('arg1', 'arg2'));
}
function it_is_prophecy_exception()
{
$this->shouldBeAnInstanceOf('Prophecy\Exception\Prophecy\ObjectProphecyException');
}
function it_exposes_method_name_through_getter()
{
$this->getMethodName()->shouldReturn('getName');
}
function it_exposes_arguments_through_getter()
{
$this->getArguments()->shouldReturn(array('arg1', 'arg2'));
}
}

View File

@@ -1,28 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Doubler;
use PhpSpec\ObjectBehavior;
use spec\Prophecy\Exception\Prophecy;
class ClassCreatorExceptionSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Doubler\Generator\Node\ClassNode $node
*/
function let($node)
{
$this->beConstructedWith('', $node);
}
function it_is_a_prophecy_exception()
{
$this->shouldBeAnInstanceOf('Prophecy\Exception\Exception');
$this->shouldBeAnInstanceOf('Prophecy\Exception\Doubler\DoublerException');
}
function it_contains_a_reflected_node($node)
{
$this->getClassNode()->shouldReturn($node);
}
}

View File

@@ -1,27 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Doubler;
use PhpSpec\ObjectBehavior;
class ClassMirrorExceptionSpec extends ObjectBehavior
{
/**
* @param \ReflectionClass $class
*/
function let($class)
{
$this->beConstructedWith('', $class);
}
function it_is_a_prophecy_exception()
{
$this->shouldBeAnInstanceOf('Prophecy\Exception\Exception');
$this->shouldBeAnInstanceOf('Prophecy\Exception\Doubler\DoublerException');
}
function it_contains_a_reflected_class_link($class)
{
$this->getReflectedClass()->shouldReturn($class);
}
}

View File

@@ -1,25 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Doubler;
use PhpSpec\ObjectBehavior;
use spec\Prophecy\Exception\Prophecy;
class ClassNotFoundExceptionSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('msg', 'CustomClass');
}
function it_is_a_prophecy_exception()
{
$this->shouldBeAnInstanceOf('Prophecy\Exception\Exception');
$this->shouldBeAnInstanceOf('Prophecy\Exception\Doubler\DoubleException');
}
function its_getClassname_returns_classname()
{
$this->getClassname()->shouldReturn('CustomClass');
}
}

View File

@@ -1,14 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Doubler;
use PhpSpec\ObjectBehavior;
class DoubleExceptionSpec extends ObjectBehavior
{
function it_is_a_double_exception()
{
$this->shouldBeAnInstanceOf('RuntimeException');
$this->shouldBeAnInstanceOf('Prophecy\Exception\Doubler\DoublerException');
}
}

View File

@@ -1,24 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Doubler;
use PhpSpec\ObjectBehavior;
use spec\Prophecy\Exception\Prophecy;
class InterfaceNotFoundExceptionSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('msg', 'CustomInterface');
}
function it_extends_ClassNotFoundException()
{
$this->shouldBeAnInstanceOf('Prophecy\Exception\Doubler\ClassNotFoundException');
}
function its_getClassname_returns_classname()
{
$this->getClassname()->shouldReturn('CustomInterface');
}
}

View File

@@ -1,29 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Doubler;
use PhpSpec\ObjectBehavior;
use spec\Prophecy\Exception\Prophecy;
class MethodNotExtendableExceptionSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('', 'User', 'getName');
}
function it_is_DoubleException()
{
$this->shouldHaveType('Prophecy\Exception\Doubler\DoubleException');
}
function it_has_MethodName()
{
$this->getMethodName()->shouldReturn('getName');
}
function it_has_classname()
{
$this->getClassName()->shouldReturn('User');
}
}

View File

@@ -1,40 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Doubler;
use PhpSpec\ObjectBehavior;
use spec\Prophecy\Exception\Prophecy;
class MethodNotFoundExceptionSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('', 'User', 'getName', array(1, 2, 3));
}
function it_is_DoubleException()
{
$this->shouldHaveType('Prophecy\Exception\Doubler\DoubleException');
}
function it_has_MethodName()
{
$this->getMethodName()->shouldReturn('getName');
}
function it_has_classnamej()
{
$this->getClassname()->shouldReturn('User');
}
function it_has_an_arguments_list()
{
$this->getArguments()->shouldReturn(array(1, 2, 3));
}
function it_has_a_default_null_argument_list()
{
$this->beConstructedWith('', 'User', 'getName');
$this->getArguments()->shouldReturn(null);
}
}

View File

@@ -1,57 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Prediction;
use PhpSpec\ObjectBehavior;
class AggregateExceptionSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith(null);
}
function it_is_prediction_exception()
{
$this->shouldBeAnInstanceOf('RuntimeException');
$this->shouldBeAnInstanceOf('Prophecy\Exception\Prediction\PredictionException');
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
*/
function it_can_store_objectProphecy_link($object)
{
$this->setObjectProphecy($object);
$this->getObjectProphecy()->shouldReturn($object);
}
function it_should_not_have_exceptions_at_the_beginning()
{
$this->getExceptions()->shouldHaveCount(0);
}
/**
* @param \Prophecy\Exception\Prediction\PredictionException $exception
*/
function it_should_append_exception_through_append_method($exception)
{
$exception->getMessage()->willReturn('Exception #1');
$this->append($exception);
$this->getExceptions()->shouldReturn(array($exception));
}
/**
* @param \Prophecy\Exception\Prediction\PredictionException $exception
*/
function it_should_update_message_during_append($exception)
{
$exception->getMessage()->willReturn('Exception #1');
$this->append($exception);
$this->getMessage()->shouldReturn(" Exception #1");
}
}

View File

@@ -1,29 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Prediction;
use PhpSpec\ObjectBehavior;
class NoCallsExceptionSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Prophecy\ObjectProphecy $objectProphecy
* @param \Prophecy\Prophecy\MethodProphecy $methodProphecy
*/
function let($objectProphecy, $methodProphecy)
{
$methodProphecy->getObjectProphecy()->willReturn($objectProphecy);
$this->beConstructedWith('message', $methodProphecy);
}
function it_is_PredictionException()
{
$this->shouldHaveType('Prophecy\Exception\Prediction\PredictionException');
}
function it_extends_MethodProphecyException()
{
$this->shouldHaveType('Prophecy\Exception\Prophecy\MethodProphecyException');
}
}

View File

@@ -1,31 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Prediction;
use PhpSpec\ObjectBehavior;
class UnexpectedCallsCountExceptionSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Prophecy\ObjectProphecy $objectProphecy
* @param \Prophecy\Prophecy\MethodProphecy $methodProphecy
* @param \Prophecy\Call\Call $call1
* @param \Prophecy\Call\Call $call2
*/
function let($objectProphecy, $methodProphecy, $call1, $call2)
{
$methodProphecy->getObjectProphecy()->willReturn($objectProphecy);
$this->beConstructedWith('message', $methodProphecy, 5, array($call1, $call2));
}
function it_extends_UnexpectedCallsException()
{
$this->shouldBeAnInstanceOf('Prophecy\Exception\Prediction\UnexpectedCallsException');
}
function it_should_expose_expectedCount_through_getter()
{
$this->getExpectedCount()->shouldReturn(5);
}
}

View File

@@ -1,36 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Prediction;
use PhpSpec\ObjectBehavior;
class UnexpectedCallsExceptionSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Prophecy\ObjectProphecy $objectProphecy
* @param \Prophecy\Prophecy\MethodProphecy $methodProphecy
* @param \Prophecy\Call\Call $call1
* @param \Prophecy\Call\Call $call2
*/
function let($objectProphecy, $methodProphecy, $call1, $call2)
{
$methodProphecy->getObjectProphecy()->willReturn($objectProphecy);
$this->beConstructedWith('message', $methodProphecy, array($call1, $call2));
}
function it_is_PredictionException()
{
$this->shouldHaveType('Prophecy\Exception\Prediction\PredictionException');
}
function it_extends_MethodProphecyException()
{
$this->shouldHaveType('Prophecy\Exception\Prophecy\MethodProphecyException');
}
function it_should_expose_calls_list_through_getter($call1, $call2)
{
$this->getCalls()->shouldReturn(array($call1, $call2));
}
}

View File

@@ -1,30 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Prophecy;
use PhpSpec\ObjectBehavior;
use spec\Prophecy\Exception\Prophecy;
class MethodProphecyExceptionSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Prophecy\ObjectProphecy $objectProphecy
* @param \Prophecy\Prophecy\MethodProphecy $methodProphecy
*/
function let($objectProphecy, $methodProphecy)
{
$methodProphecy->getObjectProphecy()->willReturn($objectProphecy);
$this->beConstructedWith('message', $methodProphecy);
}
function it_extends_DoubleException()
{
$this->shouldBeAnInstanceOf('Prophecy\Exception\Prophecy\ObjectProphecyException');
}
function it_holds_a_stub_reference($methodProphecy)
{
$this->getMethodProphecy()->shouldReturn($methodProphecy);
}
}

View File

@@ -1,27 +0,0 @@
<?php
namespace spec\Prophecy\Exception\Prophecy;
use PhpSpec\ObjectBehavior;
use spec\Prophecy\Exception\Prophecy;
class ObjectProphecyExceptionSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Prophecy\ObjectProphecy $objectProphecy
*/
function let($objectProphecy)
{
$this->beConstructedWith('message', $objectProphecy);
}
function it_should_be_a_prophecy_exception()
{
$this->shouldBeAnInstanceOf('Prophecy\Exception\Prophecy\ProphecyException');
}
function it_holds_double_reference($objectProphecy)
{
$this->getObjectProphecy()->shouldReturn($objectProphecy);
}
}

View File

@@ -1,42 +0,0 @@
<?php
namespace spec\Prophecy\Prediction;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CallPredictionSpec extends ObjectBehavior
{
function it_is_prediction()
{
$this->shouldHaveType('Prophecy\Prediction\PredictionInterface');
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
* @param \Prophecy\Call\Call $call
*/
function it_does_nothing_if_there_is_more_than_one_call_been_made($object, $method, $call)
{
$this->check(array($call), $object, $method)->shouldReturn(null);
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
*/
function it_throws_NoCallsException_if_no_calls_found($object, $method, $arguments)
{
$method->getObjectProphecy()->willReturn($object);
$method->getMethodName()->willReturn('getName');
$method->getArgumentsWildcard()->willReturn($arguments);
$arguments->__toString()->willReturn('123');
$object->reveal()->willReturn(new \stdClass());
$object->findProphecyMethodCalls('getName', Argument::any())->willReturn(array());
$this->shouldThrow('Prophecy\Exception\Prediction\NoCallsException')
->duringCheck(array(), $object, $method);
}
}

View File

@@ -1,54 +0,0 @@
<?php
namespace spec\Prophecy\Prediction;
use PhpSpec\ObjectBehavior;
class CallTimesPredictionSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith(2);
}
function it_is_prediction()
{
$this->shouldHaveType('Prophecy\Prediction\PredictionInterface');
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
* @param \Prophecy\Call\Call $call1
* @param \Prophecy\Call\Call $call2
*/
function it_does_nothing_if_there_were_exact_amount_of_calls_being_made(
$object, $method, $call1, $call2
)
{
$this->check(array($call1, $call2), $object, $method)->shouldReturn(null);
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
* @param \Prophecy\Call\Call $call
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
*/
function it_throws_UnexpectedCallsCountException_if_calls_found(
$object, $method, $call, $arguments
)
{
$method->getObjectProphecy()->willReturn($object);
$method->getMethodName()->willReturn('getName');
$method->getArgumentsWildcard()->willReturn($arguments);
$arguments->__toString()->willReturn('123');
$call->getMethodName()->willReturn('getName');
$call->getArguments()->willReturn(array(5, 4, 'three'));
$call->getCallPlace()->willReturn('unknown');
$this->shouldThrow('Prophecy\Exception\Prediction\UnexpectedCallsCountException')
->duringCheck(array($call), $object, $method);
}
}

View File

@@ -1,36 +0,0 @@
<?php
namespace spec\Prophecy\Prediction;
use PhpSpec\ObjectBehavior;
use RuntimeException;
class CallbackPredictionSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('get_class');
}
function it_is_prediction()
{
$this->shouldHaveType('Prophecy\Prediction\PredictionInterface');
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
* @param \Prophecy\Call\Call $call
*/
function it_proxies_call_to_callback($object, $method, $call)
{
$returnFirstCallCallback = function ($calls, $object, $method) {
throw new RuntimeException;
};
$this->beConstructedWith($returnFirstCallCallback);
$this->shouldThrow('RuntimeException')->duringCheck(array($call), $object, $method);
}
}

View File

@@ -1,43 +0,0 @@
<?php
namespace spec\Prophecy\Prediction;
use PhpSpec\ObjectBehavior;
class NoCallsPredictionSpec extends ObjectBehavior
{
function it_is_prediction()
{
$this->shouldHaveType('Prophecy\Prediction\PredictionInterface');
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_does_nothing_if_there_is_no_calls_made($object, $method)
{
$this->check(array(), $object, $method)->shouldReturn(null);
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
* @param \Prophecy\Call\Call $call
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
*/
function it_throws_UnexpectedCallsException_if_calls_found($object, $method, $call, $arguments)
{
$method->getObjectProphecy()->willReturn($object);
$method->getMethodName()->willReturn('getName');
$method->getArgumentsWildcard()->willReturn($arguments);
$arguments->__toString()->willReturn('123');
$call->getMethodName()->willReturn('getName');
$call->getArguments()->willReturn(array(5, 4, 'three'));
$call->getCallPlace()->willReturn('unknown');
$this->shouldThrow('Prophecy\Exception\Prediction\UnexpectedCallsException')
->duringCheck(array($call), $object, $method);
}
}

View File

@@ -1,110 +0,0 @@
<?php
namespace spec\Prophecy\Promise;
use PhpSpec\ObjectBehavior;
class CallbackPromiseSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('get_class');
}
function it_is_promise()
{
$this->shouldBeAnInstanceOf('Prophecy\Promise\PromiseInterface');
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_should_execute_closure_callback($object, $method)
{
$firstArgumentCallback = function ($args) {
return $args[0];
};
$this->beConstructedWith($firstArgumentCallback);
$this->execute(array('one', 'two'), $object, $method)->shouldReturn('one');
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_should_execute_static_array_callback($object, $method)
{
$firstArgumentCallback = array('spec\Prophecy\Promise\ClassCallback', 'staticCallbackMethod');
$this->beConstructedWith($firstArgumentCallback);
$this->execute(array('one', 'two'), $object, $method)->shouldReturn('one');
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_should_execute_instance_array_callback($object, $method)
{
$class = new ClassCallback();
$firstArgumentCallback = array($class, 'callbackMethod');
$this->beConstructedWith($firstArgumentCallback);
$this->execute(array('one', 'two'), $object, $method)->shouldReturn('one');
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_should_execute_string_function_callback($object, $method)
{
$firstArgumentCallback = 'spec\Prophecy\Promise\functionCallbackFirstArgument';
$this->beConstructedWith($firstArgumentCallback);
$this->execute(array('one', 'two'), $object, $method)->shouldReturn('one');
}
}
/**
* Class used to test callbackpromise
*
* @param array
* @return string
*/
class ClassCallback
{
/**
* @param array $args
*/
function callbackMethod($args)
{
return $args[0];
}
/**
* @param array $args
*/
static function staticCallbackMethod($args)
{
return $args[0];
}
}
/**
* Callback function used to test callbackpromise
*
* @param array
* @return string
*/
function functionCallbackFirstArgument($args)
{
return $args[0];
}

View File

@@ -1,41 +0,0 @@
<?php
namespace spec\Prophecy\Promise;
use PhpSpec\ObjectBehavior;
class ReturnArgumentPromiseSpec extends ObjectBehavior
{
function it_is_promise()
{
$this->shouldBeAnInstanceOf('Prophecy\Promise\PromiseInterface');
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_should_return_first_argument_if_provided($object, $method)
{
$this->execute(array('one', 'two'), $object, $method)->shouldReturn('one');
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_should_return_null_if_no_arguments_provided($object, $method)
{
$this->execute(array(), $object, $method)->shouldReturn(null);
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_should_return_nth_argument_if_provided($object, $method)
{
$this->beConstructedWith(1);
$this->execute(array('one', 'two'), $object, $method)->shouldReturn('two');
}
}

View File

@@ -1,61 +0,0 @@
<?php
namespace spec\Prophecy\Promise;
use PhpSpec\ObjectBehavior;
class ReturnPromiseSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith(array(42));
}
function it_is_promise()
{
$this->shouldBeAnInstanceOf('Prophecy\Promise\PromiseInterface');
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_returns_value_it_was_constructed_with($object, $method)
{
$this->execute(array(), $object, $method)->shouldReturn(42);
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_always_returns_last_value_left_in_the_return_values($object, $method)
{
$this->execute(array(), $object, $method)->shouldReturn(42);
$this->execute(array(), $object, $method)->shouldReturn(42);
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_consequently_returns_multiple_values_it_was_constructed_with($object, $method)
{
$this->beConstructedWith(array(42, 24, 12));
$this->execute(array(), $object, $method)->shouldReturn(42);
$this->execute(array(), $object, $method)->shouldReturn(24);
$this->execute(array(), $object, $method)->shouldReturn(12);
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_returns_null_if_constructed_with_empty_array($object, $method)
{
$this->beConstructedWith(array());
$this->execute(array(), $object, $method)->shouldReturn(null);
}
}

View File

@@ -1,58 +0,0 @@
<?php
namespace spec\Prophecy\Promise;
use PhpSpec\ObjectBehavior;
class ThrowPromiseSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('RuntimeException');
}
function it_is_promise()
{
$this->shouldBeAnInstanceOf('Prophecy\Promise\PromiseInterface');
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_instantiates_and_throws_exception_from_provided_classname($object, $method)
{
$this->beConstructedWith('InvalidArgumentException');
$this->shouldThrow('InvalidArgumentException')
->duringExecute(array(), $object, $method);
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_instantiates_exceptions_with_required_arguments($object, $method)
{
$this->beConstructedWith('spec\Prophecy\Promise\RequiredArgumentException');
$this->shouldThrow('spec\Prophecy\Promise\RequiredArgumentException')
->duringExecute(array(), $object, $method);
}
/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_throws_provided_exception($object, $method)
{
$this->beConstructedWith($exc = new \RuntimeException('Some exception'));
$this->shouldThrow($exc)->duringExecute(array(), $object, $method);
}
}
class RequiredArgumentException extends \Exception
{
final public function __construct($message, $code) {}
}

View File

@@ -1,384 +0,0 @@
<?php
namespace spec\Prophecy\Prophecy;
use PhpSpec\ObjectBehavior;
class ClassWithFinalMethod
{
final public function finalMethod() {}
}
class MethodProphecySpec extends ObjectBehavior
{
/**
* @param \Prophecy\Prophecy\ObjectProphecy $objectProphecy
* @param \ReflectionClass $reflection
*/
function let($objectProphecy, $reflection)
{
$objectProphecy->reveal()->willReturn($reflection);
$this->beConstructedWith($objectProphecy, 'getName', null);
}
function it_is_initializable()
{
$this->shouldHaveType('Prophecy\Prophecy\MethodProphecy');
}
function its_constructor_throws_MethodNotFoundException_for_unexisting_method($objectProphecy)
{
$this->shouldThrow('Prophecy\Exception\Doubler\MethodNotFoundException')->during(
'__construct', array($objectProphecy, 'getUnexisting', null)
);
}
/**
* @param ClassWithFinalMethod $subject
*/
function its_constructor_throws_MethodProphecyException_for_final_methods($objectProphecy, $subject)
{
$objectProphecy->reveal()->willReturn($subject);
$this->shouldThrow('Prophecy\Exception\Prophecy\MethodProphecyException')->during(
'__construct', array($objectProphecy, 'finalMethod', null)
);
}
function its_constructor_transforms_array_passed_as_3rd_argument_to_ArgumentsWildcard(
$objectProphecy
)
{
$this->beConstructedWith($objectProphecy, 'getName', array(42, 33));
$wildcard = $this->getArgumentsWildcard();
$wildcard->shouldNotBe(null);
$wildcard->__toString()->shouldReturn('exact(42), exact(33)');
}
function its_constructor_does_not_touch_third_argument_if_it_is_null($objectProphecy)
{
$this->beConstructedWith($objectProphecy, 'getName', null);
$wildcard = $this->getArgumentsWildcard();
$wildcard->shouldBe(null);
}
/**
* @param \Prophecy\Promise\PromiseInterface $promise
*/
function it_records_promise_through_will_method($promise, $objectProphecy)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$this->will($promise);
$this->getPromise()->shouldReturn($promise);
}
/**
* @param \Prophecy\Promise\PromiseInterface $promise
*/
function it_adds_itself_to_ObjectProphecy_during_call_to_will($objectProphecy, $promise)
{
$objectProphecy->addMethodProphecy($this)->shouldBeCalled();
$this->will($promise);
}
function it_adds_ReturnPromise_during_willReturn_call($objectProphecy)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$this->willReturn(42);
$this->getPromise()->shouldBeAnInstanceOf('Prophecy\Promise\ReturnPromise');
}
function it_adds_ThrowPromise_during_willThrow_call($objectProphecy)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$this->willThrow('RuntimeException');
$this->getPromise()->shouldBeAnInstanceOf('Prophecy\Promise\ThrowPromise');
}
function it_adds_ReturnArgumentPromise_during_willReturnArgument_call($objectProphecy)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$this->willReturnArgument();
$this->getPromise()->shouldBeAnInstanceOf('Prophecy\Promise\ReturnArgumentPromise');
}
function it_adds_ReturnArgumentPromise_during_willReturnArgument_call_with_index_argument($objectProphecy)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$this->willReturnArgument(1);
$promise = $this->getPromise();
$promise->shouldBeAnInstanceOf('Prophecy\Promise\ReturnArgumentPromise');
$promise->execute(array('one', 'two'), $objectProphecy, $this)->shouldReturn('two');
}
function it_adds_CallbackPromise_during_will_call_with_callback_argument($objectProphecy)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$callback = function () {};
$this->will($callback);
$this->getPromise()->shouldBeAnInstanceOf('Prophecy\Promise\CallbackPromise');
}
/**
* @param \Prophecy\Prediction\PredictionInterface $prediction
*/
function it_records_prediction_through_should_method($prediction, $objectProphecy)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$this->callOnWrappedObject('should', array($prediction));
$this->getPrediction()->shouldReturn($prediction);
}
function it_adds_CallbackPrediction_during_should_call_with_callback_argument($objectProphecy)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$callback = function () {};
$this->callOnWrappedObject('should', array($callback));
$this->getPrediction()->shouldBeAnInstanceOf('Prophecy\Prediction\CallbackPrediction');
}
/**
* @param \Prophecy\Prediction\PredictionInterface $prediction
*/
function it_adds_itself_to_ObjectProphecy_during_call_to_should($objectProphecy, $prediction)
{
$objectProphecy->addMethodProphecy($this)->shouldBeCalled();
$this->callOnWrappedObject('should', array($prediction));
}
function it_adds_CallPrediction_during_shouldBeCalled_call($objectProphecy)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$this->callOnWrappedObject('shouldBeCalled', array());
$this->getPrediction()->shouldBeAnInstanceOf('Prophecy\Prediction\CallPrediction');
}
function it_adds_NoCallsPrediction_during_shouldNotBeCalled_call($objectProphecy)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$this->callOnWrappedObject('shouldNotBeCalled', array());
$this->getPrediction()->shouldBeAnInstanceOf('Prophecy\Prediction\NoCallsPrediction');
}
function it_adds_CallTimesPrediction_during_shouldBeCalledTimes_call($objectProphecy)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$this->callOnWrappedObject('shouldBeCalledTimes', array(5));
$this->getPrediction()->shouldBeAnInstanceOf('Prophecy\Prediction\CallTimesPrediction');
}
/**
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
* @param \Prophecy\Prediction\PredictionInterface $prediction
* @param \Prophecy\Call\Call $call1
* @param \Prophecy\Call\Call $call2
*/
function it_checks_prediction_via_shouldHave_method_call(
$objectProphecy, $arguments, $prediction, $call1, $call2
)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$prediction->check(array($call1, $call2), $objectProphecy->getWrappedObject(), $this)->shouldBeCalled();
$objectProphecy->findProphecyMethodCalls('getName', $arguments)->willReturn(array($call1, $call2));
$this->withArguments($arguments);
$this->callOnWrappedObject('shouldHave', array($prediction));
}
/**
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
* @param \Prophecy\Prediction\PredictionInterface $prediction
* @param \Prophecy\Call\Call $call1
* @param \Prophecy\Call\Call $call2
*/
function it_sets_return_promise_during_shouldHave_call_if_none_was_set_before(
$objectProphecy, $arguments, $prediction, $call1, $call2
)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$prediction->check(array($call1, $call2), $objectProphecy->getWrappedObject(), $this)->shouldBeCalled();
$objectProphecy->findProphecyMethodCalls('getName', $arguments)->willReturn(array($call1, $call2));
$this->withArguments($arguments);
$this->callOnWrappedObject('shouldHave', array($prediction));
$this->getPromise()->shouldReturnAnInstanceOf('Prophecy\Promise\ReturnPromise');
}
/**
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
* @param \Prophecy\Prediction\PredictionInterface $prediction
* @param \Prophecy\Call\Call $call1
* @param \Prophecy\Call\Call $call2
* @param \Prophecy\Promise\PromiseInterface $promise
*/
function it_does_not_set_return_promise_during_shouldHave_call_if_it_was_set_before(
$objectProphecy, $arguments, $prediction, $call1, $call2, $promise
)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$prediction->check(array($call1, $call2), $objectProphecy->getWrappedObject(), $this)->shouldBeCalled();
$objectProphecy->findProphecyMethodCalls('getName', $arguments)->willReturn(array($call1, $call2));
$this->will($promise);
$this->withArguments($arguments);
$this->callOnWrappedObject('shouldHave', array($prediction));
$this->getPromise()->shouldReturn($promise);
}
/**
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
* @param \Prophecy\Prediction\PredictionInterface $prediction1
* @param \Prophecy\Prediction\PredictionInterface $prediction2
* @param \Prophecy\Call\Call $call1
* @param \Prophecy\Call\Call $call2
* @param \Prophecy\Promise\PromiseInterface $promise
*/
function it_records_checked_predictions(
$objectProphecy, $arguments, $prediction1, $prediction2, $call1, $call2, $promise
)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$prediction1->check(array($call1, $call2), $objectProphecy->getWrappedObject(), $this)->willReturn();
$prediction2->check(array($call1, $call2), $objectProphecy->getWrappedObject(), $this)->willReturn();
$objectProphecy->findProphecyMethodCalls('getName', $arguments)->willReturn(array($call1, $call2));
$this->will($promise);
$this->withArguments($arguments);
$this->callOnWrappedObject('shouldHave', array($prediction1));
$this->callOnWrappedObject('shouldHave', array($prediction2));
$this->getCheckedPredictions()->shouldReturn(array($prediction1, $prediction2));
}
/**
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
* @param \Prophecy\Prediction\PredictionInterface $prediction
* @param \Prophecy\Call\Call $call1
* @param \Prophecy\Call\Call $call2
* @param \Prophecy\Promise\PromiseInterface $promise
*/
function it_records_even_failed_checked_predictions(
$objectProphecy, $arguments, $prediction, $call1, $call2, $promise
)
{
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$prediction->check(array($call1, $call2), $objectProphecy->getWrappedObject(), $this)->willThrow(new \RuntimeException());
$objectProphecy->findProphecyMethodCalls('getName', $arguments)->willReturn(array($call1, $call2));
$this->will($promise);
$this->withArguments($arguments);
try {
$this->callOnWrappedObject('shouldHave', array($prediction));
} catch (\Exception $e) {}
$this->getCheckedPredictions()->shouldReturn(array($prediction));
}
/**
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
* @param \Prophecy\Prediction\PredictionInterface $prediction
* @param \Prophecy\Call\Call $call1
* @param \Prophecy\Call\Call $call2
*/
function it_checks_prediction_via_shouldHave_method_call_with_callback(
$objectProphecy, $arguments, $prediction, $call1, $call2
)
{
$callback = function ($calls, $object, $method) {
throw new \RuntimeException;
};
$objectProphecy->findProphecyMethodCalls('getName', $arguments)->willReturn(array($call1, $call2));
$this->withArguments($arguments);
$this->shouldThrow('RuntimeException')->duringShouldHave($callback);
}
function it_does_nothing_during_checkPrediction_if_no_prediction_set()
{
$this->checkPrediction()->shouldReturn(null);
}
/**
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
* @param \Prophecy\Prediction\PredictionInterface $prediction
* @param \Prophecy\Call\Call $call1
* @param \Prophecy\Call\Call $call2
*/
function it_checks_set_prediction_during_checkPrediction(
$objectProphecy, $arguments, $prediction, $call1, $call2
)
{
$prediction->check(array($call1, $call2), $objectProphecy->getWrappedObject(), $this)->shouldBeCalled();
$objectProphecy->findProphecyMethodCalls('getName', $arguments)->willReturn(array($call1, $call2));
$objectProphecy->addMethodProphecy($this)->willReturn(null);
$this->withArguments($arguments);
$this->callOnWrappedObject('should', array($prediction));
$this->checkPrediction();
}
function it_links_back_to_ObjectProphecy_through_getter($objectProphecy)
{
$this->getObjectProphecy()->shouldReturn($objectProphecy);
}
function it_has_MethodName()
{
$this->getMethodName()->shouldReturn('getName');
}
/**
* @param \Prophecy\Argument\ArgumentsWildcard $wildcard
*/
function it_contains_ArgumentsWildcard_it_was_constructed_with($objectProphecy, $wildcard)
{
$this->beConstructedWith($objectProphecy, 'getName', $wildcard);
$this->getArgumentsWildcard()->shouldReturn($wildcard);
}
/**
* @param \Prophecy\Argument\ArgumentsWildcard $wildcard
*/
function its_ArgumentWildcard_is_mutable_through_setter($wildcard)
{
$this->withArguments($wildcard);
$this->getArgumentsWildcard()->shouldReturn($wildcard);
}
function its_withArguments_transforms_passed_array_into_ArgumentsWildcard()
{
$this->withArguments(array(42, 33));
$wildcard = $this->getArgumentsWildcard();
$wildcard->shouldNotBe(null);
$wildcard->__toString()->shouldReturn('exact(42), exact(33)');
}
function its_withArguments_throws_exception_if_wrong_arguments_provided()
{
$this->shouldThrow('Prophecy\Exception\InvalidArgumentException')->duringWithArguments(42);
}
}

View File

@@ -1,319 +0,0 @@
<?php
namespace spec\Prophecy\Prophecy;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ObjectProphecySpec extends ObjectBehavior
{
/**
* @param \Prophecy\Doubler\LazyDouble $lazyDouble
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double
*/
function let($lazyDouble, $double)
{
$this->beConstructedWith($lazyDouble);
$lazyDouble->getInstance()->willReturn($double);
}
function it_implements_ProphecyInterface()
{
$this->shouldBeAnInstanceOf('Prophecy\Prophecy\ProphecyInterface');
}
function it_sets_parentClass_during_willExtend_call($lazyDouble)
{
$lazyDouble->setParentClass('123')->shouldBeCalled();
$this->willExtend('123');
}
function it_adds_interface_during_willImplement_call($lazyDouble)
{
$lazyDouble->addInterface('222')->shouldBeCalled();
$this->willImplement('222');
}
function it_sets_constructor_arguments_during_willBeConstructedWith_call($lazyDouble)
{
$lazyDouble->setArguments(array(1, 2, 5))->shouldBeCalled();
$this->willBeConstructedWith(array(1, 2, 5));
}
function it_does_not_have_method_prophecies_by_default()
{
$this->getMethodProphecies()->shouldHaveCount(0);
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $method1
* @param \Prophecy\Prophecy\MethodProphecy $method2
* @param \Prophecy\Argument\ArgumentsWildcard $arguments
*/
function it_should_get_method_prophecies_by_method_name($method1, $method2, $arguments)
{
$method1->getMethodName()->willReturn('getName');
$method1->getArgumentsWildcard()->willReturn($arguments);
$method2->getMethodName()->willReturn('setName');
$method2->getArgumentsWildcard()->willReturn($arguments);
$this->addMethodProphecy($method1);
$this->addMethodProphecy($method2);
$methods = $this->getMethodProphecies('setName');
$methods->shouldHaveCount(1);
$methods[0]->getMethodName()->shouldReturn('setName');
}
function it_should_return_empty_array_if_no_method_prophecies_found()
{
$methods = $this->getMethodProphecies('setName');
$methods->shouldHaveCount(0);
}
/**
* @param \Prophecy\Call\CallCenter $callCenter
*/
function it_should_proxy_makeProphecyMethodCall_to_CallCenter($lazyDouble, $callCenter)
{
$this->beConstructedWith($lazyDouble, $callCenter);
$callCenter->makeCall($this->getWrappedObject(), 'setName', array('everzet'))->willReturn(42);
$this->makeProphecyMethodCall('setName', array('everzet'))->shouldReturn(42);
}
/**
* @param \Prophecy\Call\CallCenter $callCenter
* @param \Prophecy\Prophecy\RevealerInterface $revealer
*/
function it_should_reveal_arguments_and_return_values_from_callCenter(
$lazyDouble, $callCenter, $revealer
)
{
$this->beConstructedWith($lazyDouble, $callCenter, $revealer);
$revealer->reveal(array('question'))->willReturn(array('life'));
$revealer->reveal('answer')->willReturn(42);
$callCenter->makeCall($this->getWrappedObject(), 'setName', array('life'))->willReturn('answer');
$this->makeProphecyMethodCall('setName', array('question'))->shouldReturn(42);
}
/**
* @param \Prophecy\Call\CallCenter $callCenter
* @param \Prophecy\Argument\ArgumentsWildcard $wildcard
* @param \Prophecy\Call\Call $call
*/
function it_should_proxy_getProphecyMethodCalls_to_CallCenter(
$lazyDouble, $callCenter, $wildcard, $call
)
{
$this->beConstructedWith($lazyDouble, $callCenter);
$callCenter->findCalls('setName', $wildcard)->willReturn(array($call));
$this->findProphecyMethodCalls('setName', $wildcard)->shouldReturn(array($call));
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $methodProphecy
* @param \Prophecy\Argument\ArgumentsWildcard $argumentsWildcard
*/
function its_addMethodProphecy_adds_method_prophecy(
$methodProphecy, $argumentsWildcard
)
{
$methodProphecy->getArgumentsWildcard()->willReturn($argumentsWildcard);
$methodProphecy->getMethodName()->willReturn('getUsername');
$this->addMethodProphecy($methodProphecy);
$this->getMethodProphecies()->shouldReturn(array(
'getUsername' => array($methodProphecy)
));
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $methodProphecy1
* @param \Prophecy\Prophecy\MethodProphecy $methodProphecy2
* @param \Prophecy\Argument\ArgumentsWildcard $argumentsWildcard1
* @param \Prophecy\Argument\ArgumentsWildcard $argumentsWildcard2
*/
function its_addMethodProphecy_handles_prophecies_with_different_arguments(
$methodProphecy1, $methodProphecy2, $argumentsWildcard1, $argumentsWildcard2
)
{
$methodProphecy1->getArgumentsWildcard()->willReturn($argumentsWildcard1);
$methodProphecy1->getMethodName()->willReturn('getUsername');
$methodProphecy2->getArgumentsWildcard()->willReturn($argumentsWildcard2);
$methodProphecy2->getMethodName()->willReturn('getUsername');
$this->addMethodProphecy($methodProphecy1);
$this->addMethodProphecy($methodProphecy2);
$this->getMethodProphecies()->shouldReturn(array(
'getUsername' => array(
$methodProphecy1,
$methodProphecy2,
)
));
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $methodProphecy1
* @param \Prophecy\Prophecy\MethodProphecy $methodProphecy2
* @param \Prophecy\Argument\ArgumentsWildcard $argumentsWildcard1
* @param \Prophecy\Argument\ArgumentsWildcard $argumentsWildcard2
*/
function its_addMethodProphecy_handles_prophecies_for_different_methods(
$methodProphecy1, $methodProphecy2, $argumentsWildcard1, $argumentsWildcard2
)
{
$methodProphecy1->getArgumentsWildcard()->willReturn($argumentsWildcard1);
$methodProphecy1->getMethodName()->willReturn('getUsername');
$methodProphecy2->getArgumentsWildcard()->willReturn($argumentsWildcard2);
$methodProphecy2->getMethodName()->willReturn('isUsername');
$this->addMethodProphecy($methodProphecy1);
$this->addMethodProphecy($methodProphecy2);
$this->getMethodProphecies()->shouldReturn(array(
'getUsername' => array(
$methodProphecy1
),
'isUsername' => array(
$methodProphecy2
)
));
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $methodProphecy
*/
function its_addMethodProphecy_throws_exception_when_method_has_no_ArgumentsWildcard(
$methodProphecy
)
{
$methodProphecy->getArgumentsWildcard()->willReturn(null);
$methodProphecy->getObjectProphecy()->willReturn($this);
$methodProphecy->getMethodName()->willReturn('getTitle');
$this->shouldThrow('Prophecy\Exception\Prophecy\MethodProphecyException')->duringAddMethodProphecy(
$methodProphecy
);
}
function it_returns_null_after_checkPredictions_call_if_there_is_no_method_prophecies()
{
$this->checkProphecyMethodsPredictions()->shouldReturn(null);
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $methodProphecy1
* @param \Prophecy\Prophecy\MethodProphecy $methodProphecy2
* @param \Prophecy\Argument\ArgumentsWildcard $argumentsWildcard1
* @param \Prophecy\Argument\ArgumentsWildcard $argumentsWildcard2
*/
function it_throws_AggregateException_during_checkPredictions_if_predictions_fail(
$methodProphecy1, $methodProphecy2, $argumentsWildcard1, $argumentsWildcard2
)
{
$methodProphecy1->getMethodName()->willReturn('getName');
$methodProphecy1->getArgumentsWildcard()->willReturn($argumentsWildcard1);
$methodProphecy1->checkPrediction()
->willThrow('Prophecy\Exception\Prediction\AggregateException');
$methodProphecy2->getMethodName()->willReturn('setName');
$methodProphecy2->getArgumentsWildcard()->willReturn($argumentsWildcard2);
$methodProphecy2->checkPrediction()
->willThrow('Prophecy\Exception\Prediction\AggregateException');
$this->addMethodProphecy($methodProphecy1);
$this->addMethodProphecy($methodProphecy2);
$this->shouldThrow('Prophecy\Exception\Prediction\AggregateException')
->duringCheckProphecyMethodsPredictions();
}
/**
* @param \Prophecy\Doubler\Doubler $doubler
* @param \Prophecy\Prophecy\ProphecySubjectInterface $reflection
*/
function it_returns_new_MethodProphecy_instance_for_arbitrary_call($doubler, $reflection)
{
$doubler->double(Argument::any())->willReturn($reflection);
$return = $this->getProphecy();
$return->shouldBeAnInstanceOf('Prophecy\Prophecy\MethodProphecy');
$return->getMethodName()->shouldReturn('getProphecy');
}
/**
* @param \Prophecy\Doubler\Doubler $doubler
* @param \Prophecy\Prophecy\ProphecySubjectInterface $reflection
*/
function it_returns_same_MethodProphecy_for_same_registered_signature($doubler, $reflection)
{
$doubler->double(Argument::any())->willReturn($reflection);
$this->addMethodProphecy($methodProphecy1 = $this->getProphecy(1, 2, 3));
$methodProphecy2 = $this->getProphecy(1, 2, 3);
$methodProphecy2->shouldBe($methodProphecy1);
}
/**
* @param \Prophecy\Doubler\Doubler $doubler
* @param \Prophecy\Prophecy\ProphecySubjectInterface $reflection
*/
function it_returns_new_MethodProphecy_for_different_signatures($doubler, $reflection)
{
$doubler->double(Argument::any())->willReturn($reflection);
$value = new ObjectProphecySpecFixtureB('ABC');
$value2 = new ObjectProphecySpecFixtureB('CBA');
$this->addMethodProphecy($methodProphecy1 = $this->getProphecy(1, 2, 3, $value));
$methodProphecy2 = $this->getProphecy(1, 2, 3, $value2);
$methodProphecy2->shouldNotBe($methodProphecy1);
}
/**
* @param \Prophecy\Doubler\Doubler $doubler
* @param \Prophecy\Prophecy\ProphecySubjectInterface $reflection
*/
function it_returns_new_MethodProphecy_for_all_callback_signatures($doubler, $reflection)
{
$doubler->double(Argument::any())->willReturn($reflection);
$this->addMethodProphecy($methodProphecy1 = $this->getProphecy(function(){}));
$methodProphecy2 = $this->getProphecy(function(){});
$methodProphecy2->shouldNotBe($methodProphecy1);
}
}
class ObjectProphecySpecFixtureA
{
public $errors;
}
class ObjectProphecySpecFixtureB extends ObjectProphecySpecFixtureA
{
public $errors;
public $value = null;
public function __construct($value)
{
$this->value = $value;
}
}

View File

@@ -1,51 +0,0 @@
<?php
namespace spec\Prophecy\Prophecy;
use PhpSpec\ObjectBehavior;
class RevealerSpec extends ObjectBehavior
{
function it_is_revealer()
{
$this->shouldBeAnInstanceOf('Prophecy\Prophecy\RevealerInterface');
}
/**
* @param \Prophecy\Prophecy\ProphecyInterface $prophecy
* @param \stdClass $object
*/
function it_reveals_single_instance_of_ProphecyInterface($prophecy, $object)
{
$prophecy->reveal()->willReturn($object);
$this->reveal($prophecy)->shouldReturn($object);
}
/**
* @param \Prophecy\Prophecy\ProphecyInterface $prophecy1
* @param \Prophecy\Prophecy\ProphecyInterface $prophecy2
* @param \stdClass $object1
* @param \stdClass $object2
*/
function it_reveals_instances_of_ProphecyInterface_inside_array(
$prophecy1, $prophecy2, $object1, $object2
)
{
$prophecy1->reveal()->willReturn($object1);
$prophecy2->reveal()->willReturn($object2);
$this->reveal(array(
array('item' => $prophecy2),
$prophecy1
))->shouldReturn(array(
array('item' => $object2),
$object1
));
}
function it_does_not_touch_non_prophecy_interface()
{
$this->reveal(42)->shouldReturn(42);
}
}

View File

@@ -1,91 +0,0 @@
<?php
namespace spec\Prophecy;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ProphetSpec extends ObjectBehavior
{
/**
* @param \Prophecy\Doubler\Doubler $doubler
* @param \Prophecy\Prophecy\ProphecySubjectInterface $double
*/
function let($doubler, $double)
{
$doubler->double(null, array())->willReturn($double);
$this->beConstructedWith($doubler);
}
function it_constructs_new_prophecy_on_prophesize_call()
{
$prophecy = $this->prophesize();
$prophecy->shouldBeAnInstanceOf('Prophecy\Prophecy\ObjectProphecy');
}
/**
* @param \Prophecy\Prophecy\ProphecySubjectInterface $newDouble
*/
function it_constructs_new_prophecy_with_parent_class_if_specified($doubler, $newDouble)
{
$doubler->double(Argument::any(), array())->willReturn($newDouble);
$this->prophesize('Prophecy\Prophet')->reveal()->shouldReturn($newDouble);
}
/**
* @param \Prophecy\Prophecy\ProphecySubjectInterface $newDouble
*/
function it_constructs_new_prophecy_with_interface_if_specified($doubler, $newDouble)
{
$doubler->double(null, Argument::any())->willReturn($newDouble);
$this->prophesize('ArrayAccess')->reveal()->shouldReturn($newDouble);
}
function it_exposes_all_created_prophecies_through_getter()
{
$prophecy1 = $this->prophesize();
$prophecy2 = $this->prophesize();
$this->getProphecies()->shouldReturn(array($prophecy1, $prophecy2));
}
function it_does_nothing_during_checkPredictions_call_if_no_predictions_defined()
{
$this->checkPredictions()->shouldReturn(null);
}
/**
* @param \Prophecy\Prophecy\MethodProphecy $method1
* @param \Prophecy\Prophecy\MethodProphecy $method2
* @param \Prophecy\Argument\ArgumentsWildcard $arguments1
* @param \Prophecy\Argument\ArgumentsWildcard $arguments2
*/
function it_throws_AggregateException_if_defined_predictions_fail(
$method1, $method2, $arguments1, $arguments2
)
{
$method1->getMethodName()->willReturn('getName');
$method1->getArgumentsWildcard()->willReturn($arguments1);
$method1->checkPrediction()->willReturn(null);
$method2->getMethodName()->willReturn('isSet');
$method2->getArgumentsWildcard()->willReturn($arguments2);
$method2->checkPrediction()->willThrow(
'Prophecy\Exception\Prediction\AggregateException'
);
$this->prophesize()->addMethodProphecy($method1);
$this->prophesize()->addMethodProphecy($method2);
$this->shouldThrow('Prophecy\Exception\Prediction\AggregateException')
->duringCheckPredictions();
}
function it_exposes_doubler_through_getter($doubler)
{
$this->getDoubler()->shouldReturn($doubler);
}
}

View File

@@ -1,97 +0,0 @@
<?php
namespace spec\Prophecy\Util;
use PhpSpec\ObjectBehavior;
class StringUtilSpec extends ObjectBehavior
{
function it_generates_proper_string_representation_for_integer()
{
$this->stringify(42)->shouldReturn('42');
}
function it_generates_proper_string_representation_for_string()
{
$this->stringify('some string')->shouldReturn('"some string"');
}
function it_generates_single_line_representation_for_multiline_string()
{
$this->stringify("some\nstring")->shouldReturn('"some\\nstring"');
}
function it_generates_proper_string_representation_for_double()
{
$this->stringify(42.3)->shouldReturn('42.3');
}
function it_generates_proper_string_representation_for_boolean_true()
{
$this->stringify(true)->shouldReturn('true');
}
function it_generates_proper_string_representation_for_boolean_false()
{
$this->stringify(false)->shouldReturn('false');
}
function it_generates_proper_string_representation_for_null()
{
$this->stringify(null)->shouldReturn('null');
}
function it_generates_proper_string_representation_for_empty_array()
{
$this->stringify(array())->shouldReturn('[]');
}
function it_generates_proper_string_representation_for_array()
{
$this->stringify(array('zet', 42))->shouldReturn('["zet", 42]');
}
function it_generates_proper_string_representation_for_hash_containing_one_value()
{
$this->stringify(array('ever' => 'zet'))->shouldReturn('["ever" => "zet"]');
}
function it_generates_proper_string_representation_for_hash()
{
$this->stringify(array('ever' => 'zet', 52 => 'hey', 'num' => 42))->shouldReturn(
'["ever" => "zet", 52 => "hey", "num" => 42]'
);
}
function it_generates_proper_string_representation_for_resource()
{
$resource = fopen(__FILE__, 'r');
$this->stringify($resource)->shouldReturn('stream:'.$resource);
}
/**
* @param \stdClass $object
*/
function it_generates_proper_string_representation_for_object($object)
{
$objHash = sprintf('%s:%s',
get_class($object->getWrappedObject()),
spl_object_hash($object->getWrappedObject())
) . " Object (\n 'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)\n)";
$this->stringify($object)->shouldReturn("$objHash");
}
/**
* @param stdClass $object
*/
function it_generates_proper_string_representation_for_object_without_exporting($object)
{
$objHash = sprintf('%s:%s',
get_class($object->getWrappedObject()),
spl_object_hash($object->getWrappedObject())
);
$this->stringify($object, false)->shouldReturn("$objHash");
}
}

View File

@@ -61,11 +61,11 @@ class ObjectStateToken implements TokenInterface
$actual = call_user_func(array($argument, $this->name));
$comparator = $this->comparatorFactory->getComparatorFor(
$actual, $this->value
$this->value, $actual
);
try {
$comparator->assertEquals($actual, $this->value);
$comparator->assertEquals($this->value, $actual);
return 8;
} catch (ComparisonFailure $failure) {
return false;

View File

@@ -32,7 +32,7 @@ class StringContainsToken implements TokenInterface
public function scoreArgument($argument)
{
return strpos($argument, $this->value) !== false ? 6 : false;
return is_string($argument) && strpos($argument, $this->value) !== false ? 6 : false;
}
/**

View File

@@ -12,6 +12,7 @@
namespace Prophecy\Call;
use Exception;
use Prophecy\Argument\ArgumentsWildcard;
/**
* Call object.
@@ -26,6 +27,7 @@ class Call
private $exception;
private $file;
private $line;
private $scores;
/**
* Initializes call.
@@ -44,6 +46,7 @@ class Call
$this->arguments = $arguments;
$this->returnValue = $returnValue;
$this->exception = $exception;
$this->scores = new \SplObjectStorage();
if ($file) {
$this->file = $file;
@@ -124,4 +127,36 @@ class Call
return sprintf('%s:%d', $this->file, $this->line);
}
/**
* Adds the wildcard match score for the provided wildcard.
*
* @param ArgumentsWildcard $wildcard
* @param false|int $score
*
* @return $this
*/
public function addScore(ArgumentsWildcard $wildcard, $score)
{
$this->scores[$wildcard] = $score;
return $this;
}
/**
* Returns wildcard match score for the provided wildcard. The score is
* calculated if not already done.
*
* @param ArgumentsWildcard $wildcard
*
* @return false|int False OR integer score (higher - better)
*/
public function getScore(ArgumentsWildcard $wildcard)
{
if (isset($this->scores[$wildcard])) {
return $this->scores[$wildcard];
}
return $this->scores[$wildcard] = $wildcard->scoreArguments($this->getArguments());
}
}

View File

@@ -11,6 +11,7 @@
namespace Prophecy\Call;
use Prophecy\Exception\Prophecy\MethodProphecyException;
use Prophecy\Prophecy\MethodProphecy;
use Prophecy\Prophecy\ObjectProphecy;
use Prophecy\Argument\ArgumentsWildcard;
@@ -95,20 +96,30 @@ class CallCenter
// Sort matches by their score value
@usort($matches, function ($match1, $match2) { return $match2[0] - $match1[0]; });
$score = $matches[0][0];
// If Highest rated method prophecy has a promise - execute it or return null instead
$methodProphecy = $matches[0][1];
$returnValue = null;
$exception = null;
if ($promise = $matches[0][1]->getPromise()) {
if ($promise = $methodProphecy->getPromise()) {
try {
$returnValue = $promise->execute($arguments, $prophecy, $matches[0][1]);
$returnValue = $promise->execute($arguments, $prophecy, $methodProphecy);
} catch (\Exception $e) {
$exception = $e;
}
}
$this->recordedCalls[] = new Call(
if ($methodProphecy->hasReturnVoid() && $returnValue !== null) {
throw new MethodProphecyException(
"The method \"$methodName\" has a void return type, but the promise returned a value",
$methodProphecy
);
}
$this->recordedCalls[] = $call = new Call(
$methodName, $arguments, $returnValue, $exception, $file, $line
);
$call->addScore($methodProphecy->getArgumentsWildcard(), $score);
if (null !== $exception) {
throw $exception;
@@ -130,7 +141,7 @@ class CallCenter
return array_values(
array_filter($this->recordedCalls, function (Call $call) use ($methodName, $wildcard) {
return $methodName === $call->getMethodName()
&& 0 < $wildcard->scoreArguments($call->getArguments())
&& 0 < $call->getScore($wildcard)
;
})
);
@@ -140,23 +151,79 @@ class CallCenter
array $arguments)
{
$classname = get_class($prophecy->reveal());
$argstring = implode(', ', array_map(array($this->util, 'stringify'), $arguments));
$expected = implode("\n", array_map(function (MethodProphecy $methodProphecy) {
return sprintf(' - %s(%s)',
$indentationLength = 8; // looks good
$argstring = implode(
",\n",
$this->indentArguments(
array_map(array($this->util, 'stringify'), $arguments),
$indentationLength
)
);
$expected = array();
foreach (call_user_func_array('array_merge', $prophecy->getMethodProphecies()) as $methodProphecy) {
$expected[] = sprintf(
" - %s(\n" .
"%s\n" .
" )",
$methodProphecy->getMethodName(),
$methodProphecy->getArgumentsWildcard()
implode(
",\n",
$this->indentArguments(
array_map('strval', $methodProphecy->getArgumentsWildcard()->getTokens()),
$indentationLength
)
)
);
}, call_user_func_array('array_merge', $prophecy->getMethodProphecies())));
}
return new UnexpectedCallException(
sprintf(
"Method call:\n".
" - %s(%s)\n".
"on %s was not expected, expected calls were:\n%s",
"Unexpected method call on %s:\n".
" - %s(\n".
"%s\n".
" )\n".
"expected calls were:\n".
"%s",
$methodName, $argstring, $classname, $expected
$classname, $methodName, $argstring, implode("\n", $expected)
),
$prophecy, $methodName, $arguments
);
}
private function formatExceptionMessage(MethodProphecy $methodProphecy)
{
return sprintf(
" - %s(\n".
"%s\n".
" )",
$methodProphecy->getMethodName(),
implode(
",\n",
$this->indentArguments(
array_map(
function ($token) {
return (string) $token;
},
$methodProphecy->getArgumentsWildcard()->getTokens()
),
$indentationLength
)
)
);
}
private function indentArguments(array $arguments, $indentationLength)
{
return preg_replace_callback(
'/^/m',
function () use ($indentationLength) {
return str_repeat(' ', $indentationLength);
},
$arguments
);
}
}

View File

@@ -51,7 +51,8 @@ class KeywordPatch implements ClassPatchInterface
*
* @return int Priority number (higher - earlier)
*/
public function getPriority() {
public function getPriority()
{
return 49;
}
@@ -60,7 +61,11 @@ class KeywordPatch implements ClassPatchInterface
*
* @return array
*/
private function getKeywords() {
private function getKeywords()
{
if (\PHP_VERSION_ID >= 70000) {
return array('__halt_compiler');
}
return array(
'__halt_compiler',

View File

@@ -51,23 +51,32 @@ class MagicCallPatch implements ClassPatchInterface
*/
public function apply(ClassNode $node)
{
$parentClass = $node->getParentClass();
$reflectionClass = new \ReflectionClass($parentClass);
$types = array_filter($node->getInterfaces(), function ($interface) {
return 0 !== strpos($interface, 'Prophecy\\');
});
$types[] = $node->getParentClass();
$tagList = $this->tagRetriever->getTagList($reflectionClass);
foreach ($types as $type) {
$reflectionClass = new \ReflectionClass($type);
foreach($tagList as $tag) {
$methodName = $tag->getMethodName();
while ($reflectionClass) {
$tagList = $this->tagRetriever->getTagList($reflectionClass);
if (empty($methodName)) {
continue;
}
foreach ($tagList as $tag) {
$methodName = $tag->getMethodName();
if (!$reflectionClass->hasMethod($methodName)) {
$methodNode = new MethodNode($methodName);
$methodNode->setStatic($tag->isStatic());
if (empty($methodName)) {
continue;
}
$node->addMethod($methodNode);
if (!$reflectionClass->hasMethod($methodName)) {
$methodNode = new MethodNode($methodName);
$methodNode->setStatic($tag->isStatic());
$node->addMethod($methodNode);
}
}
$reflectionClass = $reflectionClass->getParentClass();
}
}
}

View File

@@ -50,9 +50,15 @@ class ProphecySubjectPatch implements ClassPatchInterface
continue;
}
$method->setCode(
'return $this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());'
);
if ($method->getReturnType() === 'void') {
$method->setCode(
'$this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());'
);
} else {
$method->setCode(
'return $this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());'
);
}
}
$prophecySetter = new MethodNode('setProphecy');
@@ -71,7 +77,7 @@ class ProphecySubjectPatch implements ClassPatchInterface
$__call->addArgument(new ArgumentNode('name'));
$__call->addArgument(new ArgumentNode('arguments'));
$node->addMethod($__call);
$node->addMethod($__call, true);
}
$__call->setCode(<<<PHP
@@ -82,8 +88,8 @@ throw new \Prophecy\Exception\Doubler\MethodNotFoundException(
PHP
);
$node->addMethod($prophecySetter);
$node->addMethod($prophecyGetter);
$node->addMethod($prophecySetter, true);
$node->addMethod($prophecyGetter, true);
}
/**

View File

@@ -34,7 +34,6 @@ class SplFileInfoPatch implements ClassPatchInterface
if (null === $node->getParentClass()) {
return false;
}
return 'SplFileInfo' === $node->getParentClass()
|| is_subclass_of($node->getParentClass(), 'SplFileInfo')
;
@@ -61,7 +60,15 @@ class SplFileInfoPatch implements ClassPatchInterface
}
if ($this->nodeIsSplFileObject($node)) {
$constructor->setCode('return parent::__construct("' . __FILE__ .'");');
$filePath = str_replace('\\','\\\\',__FILE__);
$constructor->setCode('return parent::__construct("' . $filePath .'");');
return;
}
if ($this->nodeIsSymfonySplFileInfo($node)) {
$filePath = str_replace('\\','\\\\',__FILE__);
$constructor->setCode('return parent::__construct("' . $filePath .'", "", "");');
return;
}
@@ -102,4 +109,15 @@ class SplFileInfoPatch implements ClassPatchInterface
return 'SplFileObject' === $parent
|| is_subclass_of($parent, 'SplFileObject');
}
/**
* @param ClassNode $node
* @return boolean
*/
private function nodeIsSymfonySplFileInfo(ClassNode $node)
{
$parent = $node->getParentClass();
return 'Symfony\\Component\\Finder\\SplFileInfo' === $parent;
}
}

View File

@@ -0,0 +1,95 @@
<?php
namespace Prophecy\Doubler\ClassPatch;
use Prophecy\Doubler\Generator\Node\ClassNode;
use Prophecy\Exception\Doubler\ClassCreatorException;
class ThrowablePatch implements ClassPatchInterface
{
/**
* Checks if patch supports specific class node.
*
* @param ClassNode $node
* @return bool
*/
public function supports(ClassNode $node)
{
return $this->implementsAThrowableInterface($node) && $this->doesNotExtendAThrowableClass($node);
}
/**
* @param ClassNode $node
* @return bool
*/
private function implementsAThrowableInterface(ClassNode $node)
{
foreach ($node->getInterfaces() as $type) {
if (is_a($type, 'Throwable', true)) {
return true;
}
}
return false;
}
/**
* @param ClassNode $node
* @return bool
*/
private function doesNotExtendAThrowableClass(ClassNode $node)
{
return !is_a($node->getParentClass(), 'Throwable', true);
}
/**
* Applies patch to the specific class node.
*
* @param ClassNode $node
*
* @return void
*/
public function apply(ClassNode $node)
{
$this->checkItCanBeDoubled($node);
$this->setParentClassToException($node);
}
private function checkItCanBeDoubled(ClassNode $node)
{
$className = $node->getParentClass();
if ($className !== 'stdClass') {
throw new ClassCreatorException(
sprintf(
'Cannot double concrete class %s as well as implement Traversable',
$className
),
$node
);
}
}
private function setParentClassToException(ClassNode $node)
{
$node->setParentClass('Exception');
$node->removeMethod('getMessage');
$node->removeMethod('getCode');
$node->removeMethod('getFile');
$node->removeMethod('getLine');
$node->removeMethod('getTrace');
$node->removeMethod('getPrevious');
$node->removeMethod('getNext');
$node->removeMethod('getTraceAsString');
}
/**
* Returns patch priority, which determines when patch will be applied.
*
* @return int Priority number (higher - earlier)
*/
public function getPriority()
{
return 100;
}
}

View File

@@ -19,6 +19,16 @@ namespace Prophecy\Doubler\Generator;
*/
class ClassCodeGenerator
{
/**
* @var TypeHintReference
*/
private $typeHintReference;
public function __construct(TypeHintReference $typeHintReference = null)
{
$this->typeHintReference = $typeHintReference ?: new TypeHintReference();
}
/**
* Generates PHP code for class node.
*
@@ -60,40 +70,47 @@ class ClassCodeGenerator
$method->returnsReference() ? '&':'',
$method->getName(),
implode(', ', $this->generateArguments($method->getArguments())),
version_compare(PHP_VERSION, '7.0', '>=') && $method->hasReturnType()
? sprintf(': %s', $method->getReturnType())
: ''
$this->getReturnType($method)
);
$php .= $method->getCode()."\n";
return $php.'}';
}
/**
* @return string
*/
private function getReturnType(Node\MethodNode $method)
{
if (version_compare(PHP_VERSION, '7.1', '>=')) {
if ($method->hasReturnType()) {
return $method->hasNullableReturnType()
? sprintf(': ?%s', $method->getReturnType())
: sprintf(': %s', $method->getReturnType());
}
}
if (version_compare(PHP_VERSION, '7.0', '>=')) {
return $method->hasReturnType() && $method->getReturnType() !== 'void'
? sprintf(': %s', $method->getReturnType())
: '';
}
return '';
}
private function generateArguments(array $arguments)
{
return array_map(function (Node\ArgumentNode $argument) {
$typeHintReference = $this->typeHintReference;
return array_map(function (Node\ArgumentNode $argument) use ($typeHintReference) {
$php = '';
if (version_compare(PHP_VERSION, '7.1', '>=')) {
$php .= $argument->isNullable() ? '?' : '';
}
if ($hint = $argument->getTypeHint()) {
switch ($hint) {
case 'array':
case 'callable':
$php .= $hint;
break;
case 'string':
case 'int':
case 'float':
case 'bool':
if (version_compare(PHP_VERSION, '7.0', '>=')) {
$php .= $hint;
break;
}
// Fall-through to default case for PHP 5.x
default:
$php .= '\\'.$hint;
}
$php .= $typeHintReference->isBuiltInParamTypeHint($hint) ? $hint : '\\'.$hint;
}
$php .= ' '.($argument->isPassedByReference() ? '&' : '');

Some files were not shown because too many files have changed in this diff Show More