My first commit of codes

This commit is contained in:
sujitprasad
2015-05-01 13:13:01 +05:30
parent 4c8e5096f1
commit a6e5a69348
8487 changed files with 1317246 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
<?php
namespace spec\PhpSpec\CodeGenerator\Generator;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Console\IO;
use PhpSpec\CodeGenerator\TemplateRenderer;
use PhpSpec\Util\Filesystem;
use PhpSpec\Locator\ResourceInterface;
class ClassGeneratorSpec extends ObjectBehavior
{
function let(IO $io, TemplateRenderer $tpl, Filesystem $fs)
{
$this->beConstructedWith($io, $tpl, $fs);
}
function it_is_a_generator()
{
$this->shouldBeAnInstanceOf('PhpSpec\CodeGenerator\Generator\GeneratorInterface');
}
function it_supports_class_generation(ResourceInterface $resource)
{
$this->supports($resource, 'class', array())->shouldReturn(true);
}
function it_does_not_support_anything_else(ResourceInterface $resource)
{
$this->supports($resource, 'anything_else', array())->shouldReturn(false);
}
function its_priority_is_0()
{
$this->getPriority()->shouldReturn(0);
}
function it_generates_class_from_resource_and_puts_it_into_appropriate_folder(
$io, $tpl, $fs, ResourceInterface $resource
) {
$resource->getName()->willReturn('App');
$resource->getSrcFilename()->willReturn('/project/src/Acme/App.php');
$resource->getSrcNamespace()->willReturn('Acme');
$resource->getSrcClassname()->willReturn('Acme\App');
$values = array(
'%filepath%' => '/project/src/Acme/App.php',
'%name%' => 'App',
'%namespace%' => 'Acme',
'%namespace_block%' => "\n\nnamespace Acme;",
);
$tpl->render('class', $values)->willReturn(null);
$tpl->renderString(Argument::type('string'), $values)->willReturn('generated code');
$fs->pathExists('/project/src/Acme/App.php')->willReturn(false);
$fs->isDirectory('/project/src/Acme')->willReturn(true);
$fs->putFileContents('/project/src/Acme/App.php', 'generated code')->shouldBeCalled();
$this->generate($resource);
}
function it_uses_template_provided_by_templating_system_if_there_is_one(
$io, $tpl, $fs, ResourceInterface $resource
) {
$resource->getName()->willReturn('App');
$resource->getSrcFilename()->willReturn('/project/src/Acme/App.php');
$resource->getSrcNamespace()->willReturn('Acme');
$resource->getSrcClassname()->willReturn('Acme\App');
$values = array(
'%filepath%' => '/project/src/Acme/App.php',
'%name%' => 'App',
'%namespace%' => 'Acme',
'%namespace_block%' => "\n\nnamespace Acme;",
);
$tpl->render('class', $values)->willReturn('template code');
$tpl->renderString(Argument::type('string'), $values)->willReturn('generated code');
$fs->pathExists('/project/src/Acme/App.php')->willReturn(false);
$fs->isDirectory('/project/src/Acme')->willReturn(true);
$fs->putFileContents('/project/src/Acme/App.php', 'template code')->shouldBeCalled();
$this->generate($resource);
}
function it_creates_folder_for_class_if_needed($io, $tpl, $fs, ResourceInterface $resource)
{
$resource->getName()->willReturn('App');
$resource->getSrcFilename()->willReturn('/project/src/Acme/App.php');
$resource->getSrcNamespace()->willReturn('Acme');
$resource->getSrcClassname()->willReturn('Acme\App');
$fs->pathExists('/project/src/Acme/App.php')->willReturn(false);
$fs->isDirectory('/project/src/Acme')->willReturn(false);
$fs->makeDirectory('/project/src/Acme')->shouldBeCalled();
$fs->putFileContents('/project/src/Acme/App.php', Argument::any())->willReturn(null);
$this->generate($resource);
}
function it_asks_confirmation_if_class_already_exists(
$io, $tpl, $fs, ResourceInterface $resource
) {
$resource->getName()->willReturn('App');
$resource->getSrcFilename()->willReturn('/project/src/Acme/App.php');
$resource->getSrcNamespace()->willReturn('Acme');
$resource->getSrcClassname()->willReturn('Acme\App');
$fs->pathExists('/project/src/Acme/App.php')->willReturn(true);
$io->askConfirmation(Argument::type('string'), false)->willReturn(false);
$fs->putFileContents(Argument::cetera())->shouldNotBeCalled();
$this->generate($resource);
}
}

View File

@@ -0,0 +1,79 @@
<?php
namespace spec\PhpSpec\CodeGenerator\Generator;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Console\IO;
use PhpSpec\CodeGenerator\TemplateRenderer;
use PhpSpec\Util\Filesystem;
use PhpSpec\Locator\ResourceInterface;
class MethodGeneratorSpec extends ObjectBehavior
{
function let(IO $io, TemplateRenderer $tpl, Filesystem $fs)
{
$this->beConstructedWith($io, $tpl, $fs);
}
function it_is_a_generator()
{
$this->shouldBeAnInstanceOf('PhpSpec\CodeGenerator\Generator\GeneratorInterface');
}
function it_supports_method_generation(ResourceInterface $resource)
{
$this->supports($resource, 'method', array())->shouldReturn(true);
}
function it_does_not_support_anything_else(ResourceInterface $resource)
{
$this->supports($resource, 'anything_else', array())->shouldReturn(false);
}
function its_priority_is_0()
{
$this->getPriority()->shouldReturn(0);
}
function it_generates_class_method_from_resource($io, $tpl, $fs, ResourceInterface $resource)
{
$codeWithoutMethod = <<<CODE
<?php
namespace Acme;
class App
{
}
CODE;
$codeWithMethod = <<<CODE
<?php
namespace Acme;
class App
{
METHOD
}
CODE;
$values = array(
'%name%' => 'setName',
'%arguments%' => '$argument1',
);
$resource->getSrcFilename()->willReturn('/project/src/Acme/App.php');
$resource->getSrcClassname()->willReturn('Acme\App');
$tpl->render('method', $values)->willReturn(null);
$tpl->renderString(Argument::type('string'), $values)->willReturn('METHOD');
$fs->getFileContents('/project/src/Acme/App.php')->willReturn($codeWithoutMethod);
$fs->putFileContents('/project/src/Acme/App.php', $codeWithMethod)->shouldBeCalled();
$this->generate($resource, array('name' => 'setName', 'arguments' => array('everzet')));
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace spec\PhpSpec\CodeGenerator\Generator;
use PhpSpec\CodeGenerator\TemplateRenderer;
use PhpSpec\Console\IO;
use PhpSpec\Locator\ResourceInterface;
use PhpSpec\ObjectBehavior;
use PhpSpec\Util\Filesystem;
use Prophecy\Argument;
class NamedConstructorGeneratorSpec extends ObjectBehavior
{
function let(IO $io, TemplateRenderer $tpl, Filesystem $fs)
{
$this->beConstructedWith($io, $tpl, $fs);
}
function it_is_a_generator()
{
$this->shouldBeAnInstanceOf('PhpSpec\CodeGenerator\Generator\GeneratorInterface');
}
function it_supports_static_constructor_generation(ResourceInterface $resource)
{
$this->supports($resource, 'named_constructor', array())->shouldReturn(true);
}
function it_does_not_support_anything_else(ResourceInterface $resource)
{
$this->supports($resource, 'anything_else', array())->shouldReturn(false);
}
function its_priority_is_0()
{
$this->getPriority()->shouldReturn(0);
}
function it_generates_static_constructor_method_from_resource($io, $tpl, $fs, ResourceInterface $resource)
{
$codeWithoutMethod = <<<CODE
<?php
namespace Acme;
class App
{
}
CODE;
$codeWithMethod = <<<CODE
<?php
namespace Acme;
class App
{
METHOD
}
CODE;
$values = array(
'%methodName%' => 'setName',
'%arguments%' => '$argument1',
'%returnVar%' => '$app',
'%className%' => 'App',
'%constructorArguments%' => ''
);
$resource->getSrcFilename()->willReturn('/project/src/Acme/App.php');
$resource->getSrcClassname()->willReturn('Acme\App');
$resource->getName()->willReturn('App');
$tpl->render('named_constructor_create_object', $values)->willReturn(null);
$tpl->renderString(Argument::type('string'), $values)->willReturn('METHOD');
$fs->getFileContents('/project/src/Acme/App.php')->willReturn($codeWithoutMethod);
$fs->putFileContents('/project/src/Acme/App.php', $codeWithMethod)->shouldBeCalled();
$this->generate($resource, array('name' => 'setName', 'arguments' => array('jmurphy')));
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace spec\PhpSpec\CodeGenerator\Generator;
use PhpSpec\CodeGenerator\TemplateRenderer;
use PhpSpec\Console\IO;
use PhpSpec\ObjectBehavior;
use PhpSpec\Util\Filesystem;
use Prophecy\Argument;
use PhpSpec\Locator\ResourceInterface;
class ReturnConstantGeneratorSpec extends ObjectBehavior
{
function let(IO $io, TemplateRenderer $templates, Filesystem $filesystem)
{
$this->beConstructedWith($io, $templates, $filesystem);
}
function it_is_a_generator()
{
$this->shouldHaveType('PhpSpec\CodeGenerator\Generator\GeneratorInterface');
}
function it_supports_returnConstant_generation(ResourceInterface $resource)
{
$this->supports($resource, 'returnConstant', array())->shouldReturn(true);
}
function it_does_not_support_anything_else(ResourceInterface $resource)
{
$this->supports($resource, 'anything_else', array())->shouldReturn(false);
}
function its_priority_is_0()
{
$this->getPriority()->shouldReturn(0);
}
}

View File

@@ -0,0 +1,120 @@
<?php
namespace spec\PhpSpec\CodeGenerator\Generator;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Console\IO;
use PhpSpec\CodeGenerator\TemplateRenderer;
use PhpSpec\Util\Filesystem;
use PhpSpec\Locator\ResourceInterface;
class SpecificationGeneratorSpec extends ObjectBehavior
{
function let(IO $io, TemplateRenderer $tpl, Filesystem $fs)
{
$this->beConstructedWith($io, $tpl, $fs);
}
function it_is_a_generator()
{
$this->shouldBeAnInstanceOf('PhpSpec\CodeGenerator\Generator\GeneratorInterface');
}
function it_supports_specification_generations(ResourceInterface $resource)
{
$this->supports($resource, 'specification', array())->shouldReturn(true);
}
function it_does_not_support_anything_else(ResourceInterface $resource)
{
$this->supports($resource, 'anything_else', array())->shouldReturn(false);
}
function its_priority_is_0()
{
$this->getPriority()->shouldReturn(0);
}
function it_generates_spec_class_from_resource_and_puts_it_into_appropriate_folder(
$io, $tpl, $fs, ResourceInterface $resource
) {
$resource->getSpecName()->willReturn('App');
$resource->getSpecFilename()->willReturn('/project/spec/Acme/App.php');
$resource->getSpecNamespace()->willReturn('spec\Acme');
$resource->getSrcClassname()->willReturn('Acme\App');
$values = array(
'%filepath%' => '/project/spec/Acme/App.php',
'%name%' => 'App',
'%namespace%' => 'spec\Acme',
'%subject%' => 'Acme\App'
);
$tpl->render('specification', $values)->willReturn(null);
$tpl->renderString(Argument::type('string'), $values)->willReturn('generated code');
$fs->pathExists('/project/spec/Acme/App.php')->willReturn(false);
$fs->isDirectory('/project/spec/Acme')->willReturn(true);
$fs->putFileContents('/project/spec/Acme/App.php', 'generated code')->shouldBeCalled();
$this->generate($resource);
}
function it_uses_template_provided_by_templating_system_if_there_is_one(
$io, $tpl, $fs, ResourceInterface $resource
) {
$resource->getSpecName()->willReturn('App');
$resource->getSpecFilename()->willReturn('/project/spec/Acme/App.php');
$resource->getSpecNamespace()->willReturn('spec\Acme');
$resource->getSrcClassname()->willReturn('Acme\App');
$values = array(
'%filepath%' => '/project/spec/Acme/App.php',
'%name%' => 'App',
'%namespace%' => 'spec\Acme',
'%subject%' => 'Acme\App'
);
$tpl->render('specification', $values)->willReturn('template code');
$tpl->renderString(Argument::type('string'), $values)->willReturn('generated code');
$fs->pathExists('/project/spec/Acme/App.php')->willReturn(false);
$fs->isDirectory('/project/spec/Acme')->willReturn(true);
$fs->putFileContents('/project/spec/Acme/App.php', 'template code')->shouldBeCalled();
$this->generate($resource);
}
function it_creates_folder_for_spec_if_needed($io, $tpl, $fs, ResourceInterface $resource)
{
$resource->getSpecName()->willReturn('App');
$resource->getSpecFilename()->willReturn('/project/spec/Acme/App.php');
$resource->getSpecNamespace()->willReturn('spec\Acme');
$resource->getSrcClassname()->willReturn('Acme\App');
$fs->pathExists('/project/spec/Acme/App.php')->willReturn(false);
$fs->isDirectory('/project/spec/Acme')->willReturn(false);
$fs->makeDirectory('/project/spec/Acme')->shouldBeCalled();
$fs->putFileContents('/project/spec/Acme/App.php', Argument::any())->willReturn(null);
$this->generate($resource);
}
function it_asks_confirmation_if_spec_already_exists(
$io, $tpl, $fs, ResourceInterface $resource
) {
$resource->getSpecName()->willReturn('App');
$resource->getSpecFilename()->willReturn('/project/spec/Acme/App.php');
$resource->getSpecNamespace()->willReturn('spec\Acme');
$resource->getSrcClassname()->willReturn('Acme\App');
$fs->pathExists('/project/spec/Acme/App.php')->willReturn(true);
$io->askConfirmation(Argument::type('string'), false)->willReturn(false);
$fs->putFileContents(Argument::cetera())->shouldNotBeCalled();
$this->generate($resource);
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace spec\PhpSpec\CodeGenerator;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\CodeGenerator\Generator\GeneratorInterface;
use PhpSpec\Locator\ResourceInterface;
class GeneratorManagerSpec extends ObjectBehavior
{
function it_uses_registered_generators_to_generate_code(
GeneratorInterface $generator, ResourceInterface $resource
) {
$generator->getPriority()->willReturn(0);
$generator->supports($resource, 'specification', array())->willReturn(true);
$generator->generate($resource, array())->shouldBeCalled();
$this->registerGenerator($generator);
$this->generate($resource, 'specification');
}
function it_chooses_generator_by_priority(
GeneratorInterface $generator1, GeneratorInterface $generator2, ResourceInterface $resource
) {
$generator1->supports($resource, 'class', array('class' => 'CustomLoader'))
->willReturn(true);
$generator1->getPriority()->willReturn(0);
$generator2->supports($resource, 'class', array('class' => 'CustomLoader'))
->willReturn(true);
$generator2->getPriority()->willReturn(2);
$generator1->generate($resource, array('class' => 'CustomLoader'))->shouldNotBeCalled();
$generator2->generate($resource, array('class' => 'CustomLoader'))->shouldBeCalled();
$this->registerGenerator($generator1);
$this->registerGenerator($generator2);
$this->generate($resource, 'class', array('class' => 'CustomLoader'));
}
function it_throws_exception_if_no_generator_found(ResourceInterface $resource)
{
$this->shouldThrow()->duringGenerate($resource, 'class', array('class' => 'CustomLoader'));
}
}

View File

@@ -0,0 +1,98 @@
<?php
namespace spec\PhpSpec\CodeGenerator;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Util\Filesystem;
class TemplateRendererSpec extends ObjectBehavior
{
function let(Filesystem $fs)
{
$this->beConstructedWith($fs);
}
function it_does_not_have_registered_locations_by_default()
{
$this->getLocations()->shouldHaveCount(0);
}
function it_has_locations_setter()
{
$this->setLocations(array('location1', 'location2'));
$this->getLocations()->shouldReturn(array('location1', 'location2'));
}
function it_provides_a_method_to_prepend_location()
{
$this->setLocations(array('location1', 'location2'));
$this->prependLocation('location0');
$this->getLocations()->shouldReturn(array('location0', 'location1', 'location2'));
}
function it_provides_a_method_to_append_location()
{
$this->setLocations(array('location1', 'location2'));
$this->appendLocation('location0');
$this->getLocations()->shouldReturn(array('location1', 'location2', 'location0'));
}
function it_normalizes_locations()
{
$this->setLocations(array('lo/ca\\tion', '\\location', 'location\\'));
$this->getLocations()->shouldReturn(array(
'lo'.DIRECTORY_SEPARATOR.'ca'.DIRECTORY_SEPARATOR.'tion',
DIRECTORY_SEPARATOR.'location',
'location'
));
}
function it_reads_existing_file_from_registered_location($fs)
{
$fs->pathExists('location1'.DIRECTORY_SEPARATOR.'some_file.tpl')->willReturn(true);
$fs->getFileContents('location1'.DIRECTORY_SEPARATOR.'some_file.tpl')->willReturn('cont');
$this->setLocations(array('location1'));
$this->render('some_file')->shouldReturn('cont');
}
function it_reads_existing_file_from_first_registered_location($fs)
{
$fs->pathExists('location1'.DIRECTORY_SEPARATOR.'some_file.tpl')->willReturn(false);
$fs->pathExists('location2'.DIRECTORY_SEPARATOR.'some_file.tpl')->willReturn(true);
$fs->pathExists('location3'.DIRECTORY_SEPARATOR.'some_file.tpl')->willReturn(true);
$fs->getFileContents('location2'.DIRECTORY_SEPARATOR.'some_file.tpl')->willReturn('cont');
$fs->getFileContents('location3'.DIRECTORY_SEPARATOR.'some_file.tpl')->willReturn('cont2');
$this->setLocations(array('location1', 'location2', 'location3'));
$this->render('some_file')->shouldReturn('cont');
}
function it_replaces_placeholders_in_template_with_provided_values($fs)
{
$fs->pathExists('location1'.DIRECTORY_SEPARATOR.'some_file.tpl')->willReturn(true);
$fs->getFileContents('location1'.DIRECTORY_SEPARATOR.'some_file.tpl')
->willReturn('Template #%number%. From %spec_name% spec.');
$this->setLocations(array('location1'));
$this->render('some_file', array('%number%' => 2, '%spec_name%' => 'tpl'))
->shouldReturn('Template #2. From tpl spec.');
}
function it_can_render_template_from_string()
{
$this->renderString('Template #%number%. From %spec_name% spec.', array(
'%number%' => 2,
'%spec_name%' => 'tpl'
))->shouldReturn('Template #2. From tpl spec.');
}
function it_returns_null_if_template_is_not_found_in_any_registered_locations()
{
$this->render('some_file')->shouldReturn(null);
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace spec\PhpSpec\Config;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class OptionsConfigSpec extends ObjectBehavior
{
function it_says_rerun_is_enabled_when_setting_is_true()
{
$this->beConstructedWith(false, false, true, false, false);
$this->isReRunEnabled()->shouldReturn(true);
}
function it_says_rerun_is_not_enabled_when_setting_is_false()
{
$this->beConstructedWith(false, false, false, false, false);
$this->isReRunEnabled()->shouldReturn(false);
}
function it_says_faking_is_enabled_when_setting_is_true()
{
$this->beConstructedWith(false, false, false, true, false);
$this->isFakingEnabled()->shouldReturn(true);
}
function it_says_faking_is_not_enabled_when_setting_is_false()
{
$this->beConstructedWith(false, false, false, false, false);
$this->isFakingEnabled()->shouldReturn(false);
}
function it_says_bootstrap_path_is_false_when_setting_is_false()
{
$this->beConstructedWith(false, false, false, false, false);
$this->getBootstrapPath()->shouldReturn(false);
}
function it_returns_bootstrap_path_when_one_is_specified()
{
$this->beConstructedWith(false, false, false, false, '/path/to/file');
$this->getBootstrapPath()->shouldReturn('/path/to/file');
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace spec\PhpSpec\Console;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ApplicationSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('test');
}
function it_is_initializable()
{
$this->shouldHaveType('PhpSpec\Console\Application');
}
}

View File

@@ -0,0 +1,183 @@
<?php
namespace spec\PhpSpec\Console;
use PhpSpec\Console\Prompter;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Config\OptionsConfig;
use Symfony\Component\Console\Helper\DialogHelper;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class IOSpec extends ObjectBehavior
{
function let(InputInterface $input, OutputInterface $output, OptionsConfig $config, Prompter $prompter)
{
$input->isInteractive()->willReturn(true);
$input->getOption('no-code-generation')->willReturn(false);
$input->getOption('stop-on-failure')->willReturn(false);
$config->isCodeGenerationEnabled()->willReturn(true);
$config->isStopOnFailureEnabled()->willReturn(false);
$this->beConstructedWith($input, $output, $config, $prompter);
}
function it_has_io_interface()
{
$this->shouldHaveType('PhpSpec\IO\IOInterface');
}
function it_is_code_generation_ready_if_no_input_config_says_otherwise()
{
$this->isCodeGenerationEnabled()->shouldReturn(true);
}
function it_is_not_code_generation_ready_if_input_is_not_interactive($input)
{
$input->isInteractive()->willReturn(false);
$this->isCodeGenerationEnabled()->shouldReturn(false);
}
function it_is_not_code_generation_ready_if_command_line_option_is_set($input)
{
$input->getOption('no-code-generation')->willReturn(true);
$this->isCodeGenerationEnabled()->shouldReturn(false);
}
function it_is_not_code_generation_ready_if_config_option_is_set($config)
{
$config->isCodeGenerationEnabled()->willReturn(false);
$this->isCodeGenerationEnabled()->shouldReturn(false);
}
function it_will_not_stop_on_failure_if_no_input_config_says_otherwise()
{
$this->isStopOnFailureEnabled()->shouldReturn(false);
}
function it_will_stop_on_failure_if_command_line_option_is_set($input)
{
$input->getOption('stop-on-failure')->willReturn(true);
$this->isStopOnFailureEnabled()->shouldReturn(true);
}
function it_will_stop_on_failure_if_config_option_is_set($config)
{
$config->isStopOnFailureEnabled()->willReturn(true);
$this->isStopOnFailureEnabled()->shouldReturn(true);
}
function it_will_enable_rerunning_if_command_line_option_is_not_set_and_config_doesnt_disallow($input, $config)
{
$input->getOption('no-rerun')->willReturn(false);
$config->isReRunEnabled()->willReturn(true);
$this->isRerunEnabled()->shouldReturn(true);
}
function it_will_disable_rerunning_if_command_line_option_is_set($input, $config)
{
$input->getOption('no-rerun')->willReturn(true);
$config->isReRunEnabled()->willReturn(true);
$this->isRerunEnabled()->shouldReturn(false);
}
function it_will_disable_rerunning_if_config_option_is_set($input, $config)
{
$input->getOption('no-rerun')->willReturn(false);
$config->isReRunEnabled()->willReturn(false);
$this->isRerunEnabled()->shouldReturn(false);
}
function it_will_disable_faking_if_command_line_option_and_config_flag_are_not_set($input, $config)
{
$input->getOption('fake')->willReturn(false);
$config->isFakingEnabled()->willReturn(false);
$this->isFakingEnabled()->shouldReturn(false);
}
function it_will_enable_faking_if_command_line_option_is_set($input, $config)
{
$input->getOption('fake')->willReturn(true);
$config->isFakingEnabled()->willReturn(false);
$this->isFakingEnabled()->shouldReturn(true);
}
function it_will_enable_faking_if_config_flag_is_set($input, $config)
{
$input->getOption('fake')->willReturn(false);
$config->isFakingEnabled()->willReturn(true);
$this->isFakingEnabled()->shouldReturn(true);
}
function it_will_report_no_bootstrap_when_there_is_none($input, $config)
{
$input->getOption('bootstrap')->willReturn(null);
$config->getBootstrapPath()->willReturn(false);
$this->getBootstrapPath()->shouldReturn(false);
}
function it_will_report_bootstrap_path_when_one_is_in_the_config_file($input, $config)
{
$input->getOption('bootstrap')->willReturn(null);
$config->getBootstrapPath()->willReturn('/path/to/bootstrap.php');
$this->getBootstrapPath()->shouldReturn('/path/to/bootstrap.php');
}
function it_will_report_bootstrap_path_when_one_is_specified_at_the_command_line($input, $config)
{
$input->getOption('bootstrap')->willReturn('/path/to/bootstrap.php');
$config->getBootstrapPath()->willReturn(false);
$this->getBootstrapPath()->shouldReturn('/path/to/bootstrap.php');
}
function it_will_report_bootstrap_path_from_cli_when_different_paths_are_specified_in_config_and_cli($input, $config)
{
$input->getOption('bootstrap')->willReturn('/path/to/bootstrap.php');
$config->getBootstrapPath()->willReturn('/path/to/different.php');
$this->getBootstrapPath()->shouldReturn('/path/to/bootstrap.php');
}
function it_defaults_the_block_width()
{
$this->getBlockWidth()->shouldReturn(60);
}
function it_sets_the_block_width_to_the_minimum_when_terminal_is_narrow()
{
$this->setConsoleWidth(10);
$this->getBlockWidth()->shouldReturn(60);
}
function it_sets_the_block_width_to_the_maximum_when_terminal_is_very_wide()
{
$this->setConsoleWidth(1000);
$this->getBlockWidth()->shouldReturn(80);
}
function it_sets_the_block_width_to_narrower_than_the_terminal_width_when_terminal_is_in_range()
{
$this->setConsoleWidth(75);
$this->getBlockWidth()->shouldReturn(65);
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace spec\PhpSpec\Console;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Event\ExampleEvent;
class ResultConverterSpec extends ObjectBehavior
{
function it_converts_passed_result_code_into_0()
{
$this->convert(ExampleEvent::PASSED)->shouldReturn(0);
}
function it_converts_skipped_result_code_into_0()
{
$this->convert(ExampleEvent::SKIPPED)->shouldReturn(0);
}
function it_converts_pending_result_code_into_1()
{
$this->convert(ExampleEvent::PENDING)->shouldReturn(1);
}
function it_converts_failed_result_code_into_1()
{
$this->convert(ExampleEvent::FAILED)->shouldReturn(1);
}
function it_converts_broken_result_code_into_1()
{
$this->convert(ExampleEvent::BROKEN)->shouldReturn(1);
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace spec\PhpSpec\Event;
use PhpSpec\ObjectBehavior;
use PhpSpec\Loader\Node\ExampleNode;
use PhpSpec\Loader\Node\SpecificationNode;
use PhpSpec\Loader\Suite;
use Exception;
class ExampleEventSpec extends ObjectBehavior
{
function let(Suite $suite, SpecificationNode $specification, ExampleNode $example, Exception $exception)
{
$this->beConstructedWith($example, 10, $this->FAILED, $exception);
$example->getSpecification()->willReturn($specification);
$specification->getSuite()->willReturn($suite);
}
function it_is_an_event()
{
$this->shouldBeAnInstanceOf('Symfony\Component\EventDispatcher\Event');
$this->shouldBeAnInstanceOf('PhpSpec\Event\EventInterface');
}
function it_provides_a_link_to_example($example)
{
$this->getExample()->shouldReturn($example);
}
function it_provides_a_link_to_specification($specification)
{
$this->getSpecification()->shouldReturn($specification);
}
function it_provides_a_link_to_suite($suite)
{
$this->getSuite()->shouldReturn($suite);
}
function it_provides_a_link_to_time()
{
$this->getTime()->shouldReturn(10);
}
function it_provides_a_link_to_result()
{
$this->getResult()->shouldReturn($this->FAILED);
}
function it_provides_a_link_to_exception($exception)
{
$this->getException()->shouldReturn($exception);
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace spec\PhpSpec\Event;
use PhpSpec\ObjectBehavior;
use PhpSpec\Loader\Suite;
use PhpSpec\Loader\Node\SpecificationNode;
use PhpSpec\Loader\Node\ExampleNode;
use PhpSpec\Matcher\MatcherInterface;
use Prophecy\Argument;
use Exception;
class ExpectationEventSpec extends ObjectBehavior
{
function let(Suite $suite, SpecificationNode $specification, ExampleNode $example,
MatcherInterface $matcher, $subject, Exception $exception)
{
$method = 'calledMethod';
$arguments = array('methodArguments');
$this->beConstructedWith($example, $matcher, $subject, $method, $arguments, $this->FAILED, $exception);
$example->getSpecification()->willReturn($specification);
$specification->getSuite()->willReturn($suite);
}
function it_is_an_event()
{
$this->shouldBeAnInstanceOf('Symfony\Component\EventDispatcher\Event');
$this->shouldBeAnInstanceOf('PhpSpec\Event\EventInterface');
}
function it_provides_a_link_to_matcher($matcher)
{
$this->getMatcher()->shouldReturn($matcher);
}
function it_provides_a_link_to_example($example)
{
$this->getExample()->shouldReturn($example);
}
function it_provides_a_link_to_specification($specification)
{
$this->getSpecification()->shouldReturn($specification);
}
function it_provides_a_link_to_suite($suite)
{
$this->getSuite()->shouldReturn($suite);
}
function it_provides_a_link_to_subject($subject)
{
$this->getSubject()->shouldReturn($subject);
}
function it_provides_a_link_to_method()
{
$this->getMethod()->shouldReturn('calledMethod');
}
function it_provides_a_link_to_arguments()
{
$this->getArguments()->shouldReturn(array('methodArguments'));
}
function it_provides_a_link_to_result()
{
$this->getResult()->shouldReturn($this->FAILED);
}
function it_provides_a_link_to_exception($exception)
{
$this->getException()->shouldReturn($exception);
}
}

View File

@@ -0,0 +1,66 @@
<?php
namespace spec\PhpSpec\Event;
use PhpSpec\ObjectBehavior;
use PhpSpec\Wrapper\Subject;
use PhpSpec\Loader\Suite;
use PhpSpec\Loader\Node\SpecificationNode;
use PhpSpec\Loader\Node\ExampleNode;
use Prophecy\Argument;
class MethodCallEventSpec extends ObjectBehavior
{
function let(Suite $suite, SpecificationNode $specification, ExampleNode $example, $subject)
{
$method = 'calledMethod';
$arguments = array('methodArguments');
$returnValue = 'returned value';
$this->beConstructedWith($example, $subject, $method, $arguments, $returnValue);
$example->getSpecification()->willReturn($specification);
$specification->getSuite()->willReturn($suite);
}
function it_is_an_event()
{
$this->shouldBeAnInstanceOf('Symfony\Component\EventDispatcher\Event');
$this->shouldBeAnInstanceOf('PhpSpec\Event\EventInterface');
}
function it_provides_a_link_to_example($example)
{
$this->getExample()->shouldReturn($example);
}
function it_provides_a_link_to_specification($specification)
{
$this->getSpecification()->shouldReturn($specification);
}
function it_provides_a_link_to_suite($suite)
{
$this->getSuite()->shouldReturn($suite);
}
function it_provides_a_link_to_subject($subject)
{
$this->getSubject()->shouldReturn($subject);
}
function it_provides_a_link_to_method()
{
$this->getMethod()->shouldReturn('calledMethod');
}
function it_provides_a_link_to_arguments()
{
$this->getArguments()->shouldReturn(array('methodArguments'));
}
function it_provides_a_link_to_return_value()
{
$this->getReturnValue()->shouldReturn('returned value');
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace spec\PhpSpec\Event;
use PhpSpec\ObjectBehavior;
use PhpSpec\Event\ExampleEvent as Example;
use PhpSpec\Loader\Node\SpecificationNode;
use PhpSpec\Loader\Suite;
class SpecificationEventSpec extends ObjectBehavior
{
function let(Suite $suite, SpecificationNode $specification)
{
$this->beConstructedWith($specification, 10, Example::FAILED);
$specification->getSuite()->willReturn($suite);
}
function it_is_an_event()
{
$this->shouldBeAnInstanceOf('Symfony\Component\EventDispatcher\Event');
$this->shouldBeAnInstanceOf('PhpSpec\Event\EventInterface');
}
function it_provides_a_link_to_suite($suite)
{
$this->getSuite()->shouldReturn($suite);
}
function it_provides_a_link_to_specification($specification)
{
$this->getSpecification()->shouldReturn($specification);
}
function it_provides_a_link_to_time()
{
$this->getTime()->shouldReturn(10);
}
function it_provides_a_link_to_result()
{
$this->getResult()->shouldReturn(Example::FAILED);
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace spec\PhpSpec\Event;
use PhpSpec\ObjectBehavior;
use PhpSpec\Event\ExampleEvent as Example;
use PhpSpec\Loader\Suite;
class SuiteEventSpec extends ObjectBehavior
{
function let(Suite $suite)
{
$this->beConstructedWith($suite, 10, Example::FAILED);
}
function it_is_an_event()
{
$this->shouldBeAnInstanceOf('Symfony\Component\EventDispatcher\Event');
$this->shouldBeAnInstanceOf('PhpSpec\Event\EventInterface');
}
function it_provides_a_link_to_suite($suite)
{
$this->getSuite()->shouldReturn($suite);
}
function it_provides_a_link_to_time()
{
$this->getTime()->shouldReturn(10);
}
function it_provides_a_link_to_result()
{
$this->getResult()->shouldReturn(Example::FAILED);
}
function it_defaults_to_saying_suite_is_not_worth_rerunning()
{
$this->isWorthRerunning()->shouldReturn(false);
}
function it_can_be_told_that_the_suite_is_worth_rerunning()
{
$this->markAsWorthRerunning();
$this->isWorthRerunning()->shouldReturn(true);
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace spec\PhpSpec\Exception\Example;
use PhpSpec\ObjectBehavior;
class NotEqualExceptionSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('Not equal', 2, 5);
}
function it_is_failure()
{
$this->shouldBeAnInstanceOf('PhpSpec\Exception\Example\FailureException');
}
function it_provides_a_link_to_expected()
{
$this->getExpected()->shouldReturn(2);
}
function it_provides_a_link_to_actual()
{
$this->getActual()->shouldReturn(5);
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace spec\PhpSpec\Exception\Example;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class StopOnFailureExceptionSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('Message', 0, null, 1);
}
function it_is_an_example_exception()
{
$this->shouldBeAnInstanceOf('PhpSpec\Exception\Example\ExampleException');
}
function it_has_a_the_result_of_the_last_spec()
{
$this->getResult()->shouldReturn(1);
}
}

View File

@@ -0,0 +1,173 @@
<?php
namespace spec\PhpSpec\Exception;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
class ExceptionFactorySpec extends ObjectBehavior
{
private $fixture;
private $createdException;
function let(PresenterInterface $presenter)
{
$this->beConstructedWith($presenter);
$this->fixture = new \stdClass();
$this->fixture->subject = new \stdClass();
$this->fixture->method = 'foo';
$this->fixture->arguments = array('bar');
$this->fixture->classname = '\stdClass';
$this->fixture->property = 'zoo';
}
function it_creates_a_named_constructor_not_found_exception(PresenterInterface $presenter)
{
$presenter->presentString("{$this->fixture->classname}::{$this->fixture->method}")
->shouldBeCalled()
->willReturn("\"{$this->fixture->classname}::{$this->fixture->method}\"");
$this->fixture->message = 'Named constructor "\stdClass::foo" not found.';
$this->createdException = $this->namedConstructorNotFound(
$this->fixture->classname,
$this->fixture->method,
$this->fixture->arguments
);
$this->shouldCreateNamedConstructorNotFoundException();
}
function it_creates_a_method_not_found_exception(PresenterInterface $presenter)
{
$presenter->presentString("{$this->fixture->classname}::{$this->fixture->method}")
->shouldBeCalled()
->willReturn("\"{$this->fixture->classname}::{$this->fixture->method}\"");
$this->fixture->message = 'Method "\stdClass::foo" not found.';
$this->createdException = $this->methodNotFound(
$this->fixture->classname,
$this->fixture->method,
$this->fixture->arguments
);
$this->shouldCreateMethodNotFoundException();
}
function it_creates_a_method_not_visible_exception(PresenterInterface $presenter)
{
$presenter->presentString("{$this->fixture->classname}::{$this->fixture->method}")
->shouldBeCalled()
->willReturn("\"{$this->fixture->classname}::{$this->fixture->method}\"");
$this->fixture->message = 'Method "\stdClass::foo" not visible.';
$this->createdException = $this->methodNotVisible(
$this->fixture->classname,
$this->fixture->method,
$this->fixture->arguments
);
$this->shouldCreateMethodNotVisibleException();
}
function it_creates_a_class_not_found_exception(PresenterInterface $presenter)
{
$presenter->presentString("{$this->fixture->classname}")
->shouldBeCalled()
->willReturn("\"{$this->fixture->classname}\"");
$this->fixture->message = 'Class "\stdClass" does not exist.';
$this->createdException = $this->classNotFound(
$this->fixture->classname
);
$this->shouldCreateClassNotFoundException();
}
function it_creates_a_property_not_found_exception(PresenterInterface $presenter)
{
$presenter->presentString("{$this->fixture->property}")
->shouldBeCalled()
->willReturn("\"{$this->fixture->property}\"");
$this->fixture->message = 'Property "zoo" not found.';
$this->createdException = $this->propertyNotFound(
$this->fixture->subject,
$this->fixture->property
);
$this->shouldCreatePropertyNotFoundException();
}
function it_creates_a_calling_method_on_non_object_exception(PresenterInterface $presenter)
{
$presenter->presentString("{$this->fixture->method}()")
->shouldBeCalled()
->willReturn("\"{$this->fixture->method}()\"");
$fixtureMessage = "Call to a member function \"{$this->fixture->method}()\" on a non-object.";
$exception = $this->callingMethodOnNonObject($this->fixture->method);
$exception->shouldHaveType('PhpSpec\Exception\Wrapper\SubjectException');
$exception->getMessage()->shouldBe($fixtureMessage);
}
function it_creates_a_setting_property_on_non_object_exception(PresenterInterface $presenter)
{
$presenter->presentString("{$this->fixture->property}")
->shouldBeCalled()
->willReturn("\"{$this->fixture->property}\"");
$fixtureMessage = "Setting property \"{$this->fixture->property}\" on a non-object.";
$exception = $this->settingPropertyOnNonObject($this->fixture->property);
$exception->shouldHaveType('PhpSpec\Exception\Wrapper\SubjectException');
$exception->getMessage()->shouldBe($fixtureMessage);
}
function it_creates_an_accessing_property_on_non_object_exception(PresenterInterface $presenter)
{
$presenter->presentString("{$this->fixture->property}")
->shouldBeCalled()
->willReturn("\"{$this->fixture->property}\"");
$fixtureMessage = "Getting property \"{$this->fixture->property}\" on a non-object.";
$exception = $this->gettingPropertyOnNonObject($this->fixture->property);
$exception->shouldHaveType('PhpSpec\Exception\Wrapper\SubjectException');
$exception->getMessage()->shouldBe($fixtureMessage);
}
function shouldCreateNamedConstructorNotFoundException()
{
$this->createdException->shouldHaveType('PhpSpec\Exception\Fracture\NamedConstructorNotFoundException');
$this->createdException->getMessage()->shouldReturn($this->fixture->message);
$this->createdException->getSubject()->shouldBeLike($this->fixture->subject);
$this->createdException->getMethodName()->shouldReturn($this->fixture->method);
$this->createdException->getArguments()->shouldReturn($this->fixture->arguments);
}
function shouldCreateMethodNotFoundException()
{
$this->createdException->shouldHaveType('PhpSpec\Exception\Fracture\MethodNotFoundException');
$this->createdException->getMessage()->shouldReturn($this->fixture->message);
$this->createdException->getSubject()->shouldBeLike($this->fixture->subject);
$this->createdException->getMethodName()->shouldReturn($this->fixture->method);
$this->createdException->getArguments()->shouldReturn($this->fixture->arguments);
}
function shouldCreateMethodNotVisibleException()
{
$this->createdException->shouldHaveType('PhpSpec\Exception\Fracture\MethodNotVisibleException');
$this->createdException->getMessage()->shouldReturn($this->fixture->message);
$this->createdException->getSubject()->shouldBeLike($this->fixture->subject);
$this->createdException->getMethodName()->shouldReturn($this->fixture->method);
$this->createdException->getArguments()->shouldReturn($this->fixture->arguments);
}
function shouldCreateClassNotFoundException()
{
$this->createdException->shouldHaveType('PhpSpec\Exception\Fracture\ClassNotFoundException');
$this->createdException->getMessage()->shouldReturn($this->fixture->message);
$this->createdException->getClassname()->shouldReturn($this->fixture->classname);
}
function shouldCreatePropertyNotFoundException()
{
$this->createdException->shouldHaveType('PhpSpec\Exception\Fracture\PropertyNotFoundException');
$this->createdException->getMessage()->shouldReturn($this->fixture->message);
$this->createdException->getSubject()->shouldReturn($this->fixture->subject);
$this->createdException->getProperty()->shouldReturn($this->fixture->property);
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace spec\PhpSpec\Exception;
use PhpSpec\ObjectBehavior;
use ReflectionMethod;
class ExceptionSpec extends ObjectBehavior
{
function it_extends_basic_exception()
{
$this->shouldBeAnInstanceOf('Exception');
}
function it_could_have_a_cause(ReflectionMethod $cause)
{
$this->setCause($cause);
$this->getCause()->shouldReturn($cause);
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace spec\PhpSpec\Exception\Fracture;
use PhpSpec\ObjectBehavior;
class ClassNotFoundExceptionSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('Not equal', 'stdClass');
}
function it_is_fracture()
{
$this->shouldBeAnInstanceOf('PhpSpec\Exception\Fracture\FractureException');
}
function it_provides_a_link_to_classname()
{
$this->getClassname()->shouldReturn('stdClass');
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace spec\PhpSpec\Exception\Fracture;
use PhpSpec\ObjectBehavior;
class InterfaceNotImplementedExceptionSpec extends ObjectBehavior
{
function let($subject)
{
$this->beConstructedWith('Not equal', $subject, 'ArrayAccess');
}
function it_is_fracture()
{
$this->shouldBeAnInstanceOf('PhpSpec\Exception\Fracture\FractureException');
}
function it_provides_a_link_to_subject($subject)
{
$this->getSubject()->shouldReturn($subject);
}
function it_provides_a_link_to_interface()
{
$this->getInterface()->shouldReturn('ArrayAccess');
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace spec\PhpSpec\Exception\Fracture;
use PhpSpec\ObjectBehavior;
class MethodNotFoundExceptionSpec extends ObjectBehavior
{
function let($subject)
{
$this->beConstructedWith('No method', $subject, 'setName', array('everzet'));
}
function it_is_fracture()
{
$this->shouldBeAnInstanceOf('PhpSpec\Exception\Fracture\FractureException');
}
function it_provides_a_link_to_subject($subject)
{
$this->getSubject()->shouldReturn($subject);
}
function it_provides_a_link_to_methodName()
{
$this->getMethodName()->shouldReturn('setName');
}
function it_provides_a_link_to_arguments()
{
$this->getArguments()->shouldReturn(array('everzet'));
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace spec\PhpSpec\Exception\Fracture;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MethodNotVisibleExceptionSpec extends ObjectBehavior
{
function let($subject)
{
$this->beConstructedWith('No method', $subject, 'setName', array('everzet'));
}
function it_is_fracture()
{
$this->shouldBeAnInstanceOf('PhpSpec\Exception\Fracture\FractureException');
}
function it_provides_a_link_to_subject($subject)
{
$this->getSubject()->shouldReturn($subject);
}
function it_provides_a_link_to_methodName()
{
$this->getMethodName()->shouldReturn('setName');
}
function it_provides_a_link_to_arguments()
{
$this->getArguments()->shouldReturn(array('everzet'));
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace spec\PhpSpec\Exception\Fracture;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class NamedConstructorNotFoundExceptionSpec extends ObjectBehavior
{
function let($subject)
{
$this->beConstructedWith('No named constructor', $subject, 'setName', array('jmurphy'));
}
function it_is_fracture()
{
$this->shouldBeAnInstanceOf('PhpSpec\Exception\Fracture\FractureException');
}
function it_provides_a_link_to_subject($subject)
{
$this->getSubject()->shouldReturn($subject);
}
function it_provides_a_link_to_methodName()
{
$this->getMethodName()->shouldReturn('setName');
}
function it_provides_a_link_to_arguments()
{
$this->getArguments()->shouldReturn(array('jmurphy'));
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace spec\PhpSpec\Exception\Fracture;
use PhpSpec\ObjectBehavior;
class PropertyNotFoundExceptionSpec extends ObjectBehavior
{
function let($subject)
{
$this->beConstructedWith('No method', $subject, 'attributes');
}
function it_is_fracture()
{
$this->shouldBeAnInstanceOf('PhpSpec\Exception\Fracture\FractureException');
}
function it_provides_a_link_to_subject($subject)
{
$this->getSubject()->shouldReturn($subject);
}
function it_provides_a_link_to_property()
{
$this->getProperty()->shouldReturn('attributes');
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace spec\PhpSpec\Formatter;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\BasicFormatter;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use PhpSpec\IO\IOInterface;
use PhpSpec\Listener\StatisticsCollector;
class BasicFormatterSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter, IOInterface $io, StatisticsCollector $stats)
{
$this->beAnInstanceOf('spec\PhpSpec\Formatter\TestableBasicFormatter');
$this->beConstructedWith($presenter, $io, $stats);
}
function it_is_an_event_subscriber()
{
$this->shouldHaveType('Symfony\Component\EventDispatcher\EventSubscriberInterface');
}
function it_returns_a_list_of_subscribed_events()
{
$this::getSubscribedEvents()->shouldBe(
array(
'beforeSuite' => 'beforeSuite',
'afterSuite' => 'afterSuite',
'beforeExample' => 'beforeExample',
'afterExample' => 'afterExample',
'beforeSpecification' => 'beforeSpecification',
'afterSpecification' => 'afterSpecification'
)
);
}
}
class TestableBasicFormatter extends BasicFormatter
{
}

View File

@@ -0,0 +1,171 @@
<?php
namespace spec\PhpSpec\Formatter;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use PhpSpec\Console\IO;
use PhpSpec\Listener\StatisticsCollector;
use PhpSpec\Event\SuiteEvent;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\ObjectBehavior;
use PhpSpec\Exception\Example\PendingException;
use PhpSpec\Loader\Node\SpecificationNode;
use PhpSpec\Loader\Node\ExampleNode;
use Prophecy\Argument;
use ReflectionFunctionAbstract;
class DotFormatterSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter, IO $io, StatisticsCollector $stats)
{
$this->beConstructedWith($presenter, $io, $stats);
}
function it_is_a_console_formatter()
{
$this->shouldHaveType('PhpSpec\Formatter\ConsoleFormatter');
}
function it_outputs_a_dot_for_a_passed_example(
ExampleEvent $event,
IO $io,
StatisticsCollector $stats
) {
$event->getResult()->willReturn(ExampleEvent::PASSED);
$this->afterExample($event);
$io->write("<passed>.</passed>")->shouldHaveBeenCalled();
}
function it_outputs_a_p_for_a_pending_example(
ExampleEvent $event,
IO $io,
StatisticsCollector $stats
) {
$event->getResult()->willReturn(ExampleEvent::PENDING);
$this->afterExample($event);
$io->write('<pending>P</pending>')->shouldHaveBeenCalled();
}
function it_outputs_an_s_for_a_skipped_example(
ExampleEvent $event,
IO $io,
StatisticsCollector $stats
) {
$event->getResult()->willReturn(ExampleEvent::SKIPPED);
$this->afterExample($event);
$io->write('<skipped>S</skipped>')->shouldHaveBeenCalled();
}
function it_outputs_an_f_for_a_failed_example(
ExampleEvent $event,
IO $io,
StatisticsCollector $stats
) {
$event->getResult()->willReturn(ExampleEvent::FAILED);
$this->afterExample($event);
$io->write('<failed>F</failed>')->shouldHaveBeenCalled();
}
function it_outputs_a_b_for_a_broken_example(
ExampleEvent $event,
IO $io,
StatisticsCollector $stats
) {
$event->getResult()->willReturn(ExampleEvent::BROKEN);
$this->afterExample($event);
$io->write('<broken>B</broken>')->shouldHaveBeenCalled();
}
function it_outputs_the_progress_every_50_examples(
ExampleEvent $exampleEvent,
SuiteEvent $suiteEvent,
IO $io,
StatisticsCollector $stats
) {
$exampleEvent->getResult()->willReturn(ExampleEvent::PASSED);
$suiteEvent->getSuite()->willReturn(range(1, 100));
$stats->getEventsCount()->willReturn(50);
$this->beforeSuite($suiteEvent);
$this->afterExample($exampleEvent);
$io->write(' 50 / 100')->shouldHaveBeenCalled();
}
function it_outputs_exceptions_for_failed_examples(
SuiteEvent $event,
ExampleEvent $pendingEvent,
IO $io,
StatisticsCollector $stats,
SpecificationNode $specification,
ExampleNode $example,
ReflectionFunctionAbstract $reflectionFunction
) {
$reflectionFunction->getStartLine()->willReturn(37);
$example->getFunctionReflection()->willReturn($reflectionFunction);
$example->getTitle()->willReturn('it tests something');
$pendingEvent->getException()->willReturn(new PendingException());
$pendingEvent->getSpecification()->willReturn($specification);
$pendingEvent->getExample()->willReturn($example);
$stats->getEventsCount()->willReturn(1);
$stats->getFailedEvents()->willReturn(array());
$stats->getBrokenEvents()->willReturn(array());
$stats->getPendingEvents()->willReturn(array($pendingEvent));
$stats->getSkippedEvents()->willReturn(array());
$stats->getTotalSpecs()->willReturn(1);
$stats->getCountsHash()->willReturn(array(
'passed' => 0,
'pending' => 1,
'skipped' => 0,
'failed' => 0,
'broken' => 0,
));
$this->afterSuite($event);
$expected = '<lineno> 37</lineno> <pending>- it tests something</pending>';
$io->writeln($expected)->shouldHaveBeenCalled();
}
function it_outputs_a_suite_summary(
SuiteEvent $event,
IO $io,
StatisticsCollector $stats
) {
$stats->getEventsCount()->willReturn(1);
$stats->getFailedEvents()->willReturn(array());
$stats->getBrokenEvents()->willReturn(array());
$stats->getPendingEvents()->willReturn(array());
$stats->getSkippedEvents()->willReturn(array());
$stats->getTotalSpecs()->willReturn(15);
$event->getTime()->willReturn(12.345);
$stats->getCountsHash()->willReturn(array(
'passed' => 1,
'pending' => 0,
'skipped' => 0,
'failed' => 2,
'broken' => 0,
));
$this->afterSuite($event);
$io->writeln('15 specs')->shouldHaveBeenCalled();
$io->writeln("\n12345ms")->shouldHaveBeenCalled();
$io->write('1 example ')->shouldHaveBeenCalled();
$expected = '(<passed>1 passed</passed>, <failed>2 failed</failed>)';
$io->write($expected)->shouldHaveBeenCalled();
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace spec\PhpSpec\Formatter\Html;
use PhpSpec\Formatter\Presenter\Differ\Differ;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Exception\Exception;
class HtmlPresenterSpec extends ObjectBehavior
{
function let(Differ $differ)
{
$this->beConstructedWith($differ);
}
function it_is_initializable()
{
$this->shouldImplement('PhpSpec\Formatter\Presenter\PresenterInterface');
}
function it_presents_the_code_around_where_exception_was_thrown(Exception $e)
{
$e->getCause()->willReturn(new \ReflectionClass($this));
$this->presentException($e, true);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace spec\PhpSpec\Formatter\Html;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Symfony\Component\Console\Input\InputInterface;
class IOSpec extends ObjectBehavior
{
function let(InputInterface $input)
{
$this->beConstructedWith($input);
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace spec\PhpSpec\Formatter\Html;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Formatter\Presenter\PresenterInterface as Presenter;
use PhpSpec\Formatter\Html\Template;
class ReportFailedItemSpec extends ObjectBehavior
{
const EVENT_TITLE = 'it does not works';
const EVENT_MESSAGE = 'oops';
static $BACKTRACE = array(
array('line' => 42, 'file' => '/some/path/to/SomeException.php')
);
const BACKTRACE = "#42 /some/path/to/SomeException.php";
const CODE = 'code';
function let(Template $template, ExampleEvent $event, Presenter $presenter)
{
$this->beConstructedWith($template, $event, $presenter);
}
function it_writes_a_fail_message_for_a_failing_example(Template $template, ExampleEvent $event, Presenter $presenter)
{
$event->getTitle()->willReturn(self::EVENT_TITLE);
$event->getMessage()->willReturn(self::EVENT_MESSAGE);
$event->getBacktrace()->willReturn(self::$BACKTRACE);
$event->getException()->willReturn(new \Exception());
$template->render(Template::DIR.'/Template/ReportFailed.html', array(
'title' => self::EVENT_TITLE,
'message' => self::EVENT_MESSAGE,
'backtrace' => self::BACKTRACE,
'code' => self::CODE,
'index' => 1,
'specification' => 1
))->shouldBeCalled();
$presenter->presentException(Argument::cetera())->willReturn(self::CODE);
$this->write(1);
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace spec\PhpSpec\Formatter\Html;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Formatter\Template;
use PhpSpec\Formatter\Presenter\PresenterInterface as Presenter;
class ReportItemFactorySpec extends ObjectBehavior
{
function let(Template $template)
{
$this->beConstructedWith($template);
}
function it_creates_a_ReportPassedItem(ExampleEvent $event, Presenter $presenter)
{
$event->getResult()->willReturn(ExampleEvent::PASSED);
$this->create($event, $presenter)->shouldHaveType('PhpSpec\Formatter\Html\ReportPassedItem');
}
function it_creates_a_ReportPendingItem(ExampleEvent $event, Presenter $presenter)
{
$event->getResult()->willReturn(ExampleEvent::PENDING);
$this->create($event, $presenter)->shouldHaveType('PhpSpec\Formatter\Html\ReportPendingItem');
}
function it_creates_a_ReportFailedItem(ExampleEvent $event, Presenter $presenter)
{
$event->getResult()->willReturn(ExampleEvent::FAILED);
$this->create($event, $presenter)->shouldHaveType('PhpSpec\Formatter\Html\ReportFailedItem');
}
function it_creates_a_ReportBrokenItem(ExampleEvent $event, Presenter $presenter)
{
$event->getResult()->willReturn(ExampleEvent::BROKEN);
$this->create($event, $presenter)->shouldHaveType('PhpSpec\Formatter\Html\ReportFailedItem');
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace spec\PhpSpec\Formatter\Html;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Formatter\Html\Template;
class ReportPassedItemSpec extends ObjectBehavior
{
const EVENT_TITLE = 'it works';
function let(Template $template, ExampleEvent $event)
{
$this->beConstructedWith($template, $event);
}
function it_writes_a_pass_message_for_a_passing_example(Template $template, ExampleEvent $event)
{
$event->getTitle()->willReturn(self::EVENT_TITLE);
$template->render(Template::DIR.'/Template/ReportPass.html', array(
'title' => self::EVENT_TITLE
))->shouldBeCalled();
$this->write();
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace spec\PhpSpec\Formatter\Html;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Formatter\Html\Template;
class ReportPendingItemSpec extends ObjectBehavior
{
const EVENT_TITLE = 'it works';
function let(Template $template, ExampleEvent $event)
{
$this->beConstructedWith($template, $event);
}
function it_writes_a_pass_message_for_a_passing_example(Template $template, ExampleEvent $event)
{
$event->getTitle()->willReturn(self::EVENT_TITLE);
$template->render(Template::DIR.'/Template/ReportPending.html', array(
'title' => self::EVENT_TITLE,
'pendingExamplesCount' => 1
))->shouldBeCalled();
$this->write();
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace spec\PhpSpec\Formatter\Html;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\IO\IOInterface;
class TemplateSpec extends ObjectBehavior
{
function let(IOInterface $io)
{
$this->beConstructedWith($io);
}
function it_renders_the_string_as_is($io)
{
$this->render('text');
$io->write('text')->shouldHaveBeenCalled();
}
function it_renders_a_variable($io)
{
$this->render('hello {name}', array('name' => 'Chuck Norris'));
$io->write('hello Chuck Norris')->shouldHaveBeenCalled();
}
function it_works_for_many_instances_of_vars($io)
{
$this->render('{name}! {greeting}, {name}', array(
'name' => 'Chuck',
'greeting' => 'hello'
));
$io->write('Chuck! hello, Chuck')->shouldHaveBeenCalled();
}
function it_renders_a_file($io)
{
$tempFile = __DIR__."/_files/TemplateRenderFixture.tpl";
mkdir(__DIR__."/_files");
file_put_contents($tempFile, 'hello, {name}');
$this->render($tempFile, array('name' => 'Chuck'));
$io->write('hello, Chuck')->shouldHaveBeenCalled();
}
function letgo()
{
if (file_exists(__DIR__."/_files/TemplateRenderFixture.tpl")) {
unlink(__DIR__."/_files/TemplateRenderFixture.tpl");
rmdir(__DIR__."/_files");
}
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace spec\PhpSpec\Formatter;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Formatter\Html\IO;
use PhpSpec\Formatter\Html\ReportItem;
use PhpSpec\Formatter\Html\ReportItemFactory;
use PhpSpec\Formatter\Presenter\PresenterInterface as Presenter;
use PhpSpec\Listener\StatisticsCollector;
class HtmlFormatterSpec extends ObjectBehavior
{
const EVENT_TITLE = 'it works';
function let(ReportItemFactory $factory, Presenter $presenter, IO $io, StatisticsCollector $stats)
{
$this->beConstructedWith($factory, $presenter, $io, $stats);
}
function it_is_an_event_subscriber()
{
$this->shouldHaveType('Symfony\Component\EventDispatcher\EventSubscriberInterface');
}
function it_delegates_the_reporting_to_the_event_type_line_reporter(
ExampleEvent $event, ReportItem $item, ReportItemFactory $factory,
Presenter $presenter)
{
$factory->create($event, $presenter)->willReturn($item);
$item->write(Argument::any())->shouldBeCalled();
$this->afterExample($event);
}
}

View File

@@ -0,0 +1,226 @@
<?php
namespace spec\PhpSpec\Formatter;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use PhpSpec\IO\IOInterface;
use PhpSpec\Listener\StatisticsCollector;
use PhpSpec\Event\SpecificationEvent;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Loader\Node\SpecificationNode;
use PhpSpec\Event\SuiteEvent;
use PhpSpec\Exception\Example\SkippingException;
class JUnitFormatterSpec extends ObjectBehavior
{
function let(
PresenterInterface $presenter,
IOInterface $io,
StatisticsCollector $stats
) {
$this->beConstructedWith($presenter, $io, $stats);
}
function it_is_an_event_subscriber()
{
$this->shouldHaveType('Symfony\Component\EventDispatcher\EventSubscriberInterface');
}
function it_stores_a_testcase_node_after_passed_example_run(
ExampleEvent $event,
SpecificationNode $specification,
\ReflectionClass $refClass
) {
$event->getResult()->willReturn(ExampleEvent::PASSED);
$event->getTitle()->willReturn('example title');
$event->getTime()->willReturn(1337);
$event->getSpecification()->willReturn($specification);
$specification->getClassReflection()->willReturn($refClass);
$refClass->getName()->willReturn('Acme\Foo\Bar');
$this->afterExample($event);
$this->getTestCaseNodes()->shouldReturn(array(
'<testcase name="example title" time="1337" classname="Acme\Foo\Bar" status="passed" />'
));
}
function it_stores_a_testcase_node_after_broken_example_run(
ExampleEvent $event,
SpecificationNode $specification,
\ReflectionClass $refClass
) {
$event->getResult()->willReturn(ExampleEvent::BROKEN);
$event->getTitle()->willReturn('example title');
$event->getTime()->willReturn(1337);
$event->getException()->willReturn(new ExceptionStub('Something went wrong', 'Exception trace'));
$event->getSpecification()->willReturn($specification);
$specification->getClassReflection()->willReturn($refClass);
$refClass->getName()->willReturn('Acme\Foo\Bar');
$this->afterExample($event);
$this->getTestCaseNodes()->shouldReturn(array(
'<testcase name="example title" time="1337" classname="Acme\Foo\Bar" status="broken">'."\n".
'<error type="spec\PhpSpec\Formatter\ExceptionStub" message="Something went wrong" />'."\n".
'<system-err>'."\n".
'<![CDATA['."\n".
'Exception trace'."\n".
']]>'."\n".
'</system-err>'."\n".
'</testcase>'
));
}
function it_stores_a_testcase_node_after_failed_example_run(
ExampleEvent $event,
SpecificationNode $specification,
\ReflectionClass $refClass
) {
$event->getResult()->willReturn(ExampleEvent::FAILED);
$event->getTitle()->willReturn('example title');
$event->getTime()->willReturn(1337);
$event->getException()->willReturn(new ExceptionStub('Something went wrong', 'Exception trace'));
$event->getSpecification()->willReturn($specification);
$specification->getClassReflection()->willReturn($refClass);
$refClass->getName()->willReturn('Acme\Foo\Bar');
$this->afterExample($event);
$this->getTestCaseNodes()->shouldReturn(array(
'<testcase name="example title" time="1337" classname="Acme\Foo\Bar" status="failed">'."\n".
'<failure type="spec\PhpSpec\Formatter\ExceptionStub" message="Something went wrong" />'."\n".
'<system-err>'."\n".
'<![CDATA['."\n".
'Exception trace'."\n".
']]>'."\n".
'</system-err>'."\n".
'</testcase>'
));
}
function it_stores_a_testcase_node_after_skipped_example_run(
ExampleEvent $event,
SpecificationNode $specification,
\ReflectionClass $refClass
) {
$event->getResult()->willReturn(ExampleEvent::SKIPPED);
$event->getTitle()->willReturn('example title');
$event->getTime()->willReturn(1337);
$event->getException()->willReturn(new SkippingException('zog zog'));
$event->getSpecification()->willReturn($specification);
$specification->getClassReflection()->willReturn($refClass);
$refClass->getName()->willReturn('Acme\Foo\Bar');
$this->afterExample($event);
// skipped tag is escaped because a skipped tag is also registered in the console formatter
$this->getTestCaseNodes()->shouldReturn(array(
'<testcase name="example title" time="1337" classname="Acme\Foo\Bar" status="skipped">'."\n".
'\<skipped><![CDATA[ skipped: zog zog ]]>\</skipped>'."\n".
'</testcase>'
));
}
function it_aggregates_testcase_nodes_and_store_them_after_specification_run(SpecificationEvent $event)
{
$event->getTitle()->willReturn('specification title');
$event->getTime()->willReturn(42);
$this->setTestCaseNodes(array(
'<testcase name="example1" />',
'<testcase name="example2" />',
'<testcase name="example3" />',
));
$this->setExampleStatusCounts(array(
ExampleEvent::FAILED => 1,
ExampleEvent::BROKEN => 2,
ExampleEvent::PENDING => 5,
ExampleEvent::SKIPPED => 3,
));
$this->afterSpecification($event);
$this->getTestSuiteNodes()->shouldReturn(array(
'<testsuite name="specification title" time="42" tests="3" failures="1" errors="2" skipped="8">'."\n".
'<testcase name="example1" />'."\n".
'<testcase name="example2" />'."\n".
'<testcase name="example3" />'."\n".
'</testsuite>'
));
$this->getTestCaseNodes()->shouldHaveCount(0);
$this->getExampleStatusCounts()->shouldReturn(array(
ExampleEvent::PASSED => 0,
ExampleEvent::PENDING => 0,
ExampleEvent::SKIPPED => 0,
ExampleEvent::FAILED => 0,
ExampleEvent::BROKEN => 0,
));
}
function it_aggregates_testsuite_nodes_and_display_them_after_suite_run(SuiteEvent $event, $io, $stats)
{
$event->getTime()->willReturn(48151.62342);
$stats->getFailedEvents()->willReturn(range(1, 12));
$stats->getBrokenEvents()->willReturn(range(1, 3));
$stats->getEventsCount()->willReturn(100);
$this->setTestSuiteNodes(array(
'<testsuite name="specification1" tests="3">'."\n".
'<testcase name="example1" />'."\n".
'<testcase name="example2" />'."\n".
'<testcase name="example3" />'."\n".
'</testsuite>',
'<testsuite name="specification2" tests="2">'."\n".
'<testcase name="example1" />'."\n".
'<testcase name="example2" />'."\n".
'</testsuite>'
));
$this->afterSuite($event);
$io->write(
'<?xml version="1.0" encoding="UTF-8" ?>'."\n".
'<testsuites time="48151.62342" tests="100" failures="12" errors="3">'."\n".
'<testsuite name="specification1" tests="3">'."\n".
'<testcase name="example1" />'."\n".
'<testcase name="example2" />'."\n".
'<testcase name="example3" />'."\n".
'</testsuite>'."\n".
'<testsuite name="specification2" tests="2">'."\n".
'<testcase name="example1" />'."\n".
'<testcase name="example2" />'."\n".
'</testsuite>'."\n".
'</testsuites>'
)->shouldBeCalled();
}
}
class ExceptionStub
{
protected $trace;
protected $message;
public function __construct($message, $trace)
{
$this->message = $message;
$this->trace = $trace;
}
public function getMessage()
{
return $this->message;
}
public function getTraceAsString()
{
return $this->trace;
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace spec\PhpSpec\Formatter\Presenter\Differ;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ArrayEngineSpec extends ObjectBehavior
{
function it_is_a_diff_engine()
{
$this->shouldBeAnInstanceOf('PhpSpec\Formatter\Presenter\Differ\EngineInterface');
}
function it_supports_arrays()
{
$this->supports(array(), array(1, 2, 3))->shouldReturn(true);
}
function it_does_not_support_anything_else()
{
$this->supports('str', 2)->shouldReturn(false);
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace spec\PhpSpec\Formatter\Presenter\Differ;
use PhpSpec\ObjectBehavior;
use PhpSpec\Formatter\Presenter\Differ\EngineInterface;
class DifferSpec extends ObjectBehavior
{
function it_chooses_proper_engine_based_on_values(
EngineInterface $engine1, EngineInterface $engine2
) {
$engine1->supports('string1', 'string2')->willReturn(true);
$engine2->supports('string1', 'string2')->willReturn(false);
$engine1->compare('string1', 'string2')->willReturn('string1 !== string2');
$engine1->supports(2, 1)->willReturn(false);
$engine2->supports(2, 1)->willReturn(true);
$engine2->compare(2, 1)->willReturn('2 !== 1');
$this->addEngine($engine1);
$this->addEngine($engine2);
$this->compare('string1', 'string2')->shouldReturn('string1 !== string2');
$this->compare(2, 1)->shouldReturn('2 !== 1');
}
function it_returns_null_if_engine_not_found()
{
$this->compare(1, 2)->shouldReturn(null);
}
function its_constructor_allows_a_list_of_engines(EngineInterface $engine)
{
$this->beConstructedWith(array($engine));
$engine->supports('string1', 'string2')->willReturn(true);
$engine->compare('string1', 'string2')->willReturn('string1 !== string2');
$this->compare('string1', 'string2')->shouldReturn('string1 !== string2');
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace spec\PhpSpec\Formatter\Presenter\Differ;
use PhpSpec\Formatter\Presenter\Differ\StringEngine;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use SebastianBergmann\Exporter\Exporter;
class ObjectEngineSpec extends ObjectBehavior
{
function let(Exporter $exporter, StringEngine $stringDiffer)
{
$this->beConstructedWith($exporter, $stringDiffer);
}
function it_is_a_differ_engine()
{
$this->shouldHaveType('PhpSpec\Formatter\Presenter\Differ\EngineInterface');
}
function it_does_not_support_scalars()
{
$this->supports(1, 2)->shouldReturn(false);
}
function it_only_supports_objects()
{
$this->supports(new \StdClass(), new \StdClass())->shouldReturn(true);
}
function it_converts_objects_to_string_and_diffs_the_result(Exporter $exporter, StringEngine $stringDiffer)
{
$exporter->export(Argument::type('DateTime'))->willReturn('DateTime');
$exporter->export(Argument::type('ArrayObject'))->willReturn('ArrayObject');
$stringDiffer->compare('DateTime', 'ArrayObject')->willReturn('-DateTime+ArrayObject');
$diff = $this->compare(new \DateTime(), new \ArrayObject());
$diff->shouldBe('-DateTime+ArrayObject');
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace spec\PhpSpec\Formatter\Presenter\Differ;
use PhpSpec\ObjectBehavior;
class StringEngineSpec extends ObjectBehavior
{
function it_is_a_diff_engine()
{
$this->shouldBeAnInstanceOf('PhpSpec\Formatter\Presenter\Differ\EngineInterface');
}
function it_supports_string_values()
{
$this->supports('string1', 'string2')->shouldReturn(true);
}
function it_calculates_strings_diff()
{
$expected = <<<DIFF
<code>
@@ -1,1 +1,1 @@
<diff-del>-string1</diff-del>
<diff-add>+string2</diff-add>
</code>
DIFF;
$this->compare('string1', 'string2')->shouldReturn(str_replace("\n", PHP_EOL, $expected));
}
}

View File

@@ -0,0 +1,151 @@
<?php
namespace spec\PhpSpec\Formatter\Presenter;
use PhpSpec\ObjectBehavior;
use PhpSpec\Formatter\Presenter\Differ\Differ;
class StringPresenterSpec extends ObjectBehavior
{
function let(Differ $differ)
{
$this->beConstructedWith($differ);
}
function it_presents_short_string_in_quotes()
{
$this->presentValue('some_string')->shouldReturn('"some_string"');
}
function it_presents_long_string_in_quotes_but_trimmed()
{
$this->presentValue('some_string_longer_than_twenty_five_chars')
->shouldReturn('"some_string_longer_than_t..."');
}
function it_presents_only_first_line_of_multiline_string()
{
$this->presentValue("some\nmultiline\nvalue")->shouldReturn('"some..."');
}
function it_presents_simple_type_as_typed_value()
{
$this->presentValue(42)->shouldReturn('[integer:42]');
$this->presentValue(42.0)->shouldReturn('[double:42]');
}
function it_presents_object_as_classname()
{
$this->presentValue(new \stdClass())->shouldReturn('[obj:stdClass]');
}
function it_presents_array_as_elements_count()
{
$this->presentValue(array(1, 2, 3))->shouldReturn('[array:3]');
}
function it_presents_boolean_as_string()
{
$this->presentValue(true)->shouldReturn('true');
$this->presentValue(false)->shouldReturn('false');
}
function it_presents_closure_as_type()
{
$this->presentValue(function () {})->shouldReturn('[closure]');
}
function it_presents_exception_as_class_with_constructor()
{
$this->presentValue(new \RuntimeException('message'))
->shouldReturn('[exc:RuntimeException("message")]');
}
function it_presents_function_callable_as_string()
{
$this->presentValue('date')
->shouldReturn('[date()]');
}
function it_presents_method_as_string(WithMethod $object)
{
$className = get_class($object->getWrappedObject());
$this->presentValue(array($object, 'specMethod'))
->shouldReturn(sprintf('[obj:%s]::specMethod()', $className));
}
function it_presents_magic_method_as_string(WithMagicCall $object)
{
$className = get_class($object->getWrappedObject());
$this->presentValue(array($object, 'undefinedMethod'))
->shouldReturn(sprintf('[obj:%s]::undefinedMethod()', $className));
}
function it_presents_static_method_as_string(WithMethod $object)
{
$className = get_class($object->getWrappedObject());
$this->presentValue(array($className, 'specMethod'))
->shouldReturn(sprintf('%s::specMethod()', $className));
}
function it_presents_static_magic_method_as_string()
{
$className = __NAMESPACE__ . '\\WithStaticMagicCall';
$this->presentValue(array($className, 'undefinedMethod'))
->shouldReturn(sprintf('%s::undefinedMethod()', $className));
}
function it_presents_invokable_object_as_string(WithMagicInvoke $object)
{
$className = get_class($object->getWrappedObject());
$this->presentValue($object)
->shouldReturn(sprintf('[obj:%s]', $className));
}
function it_presents_string_as_string()
{
$this->presentString('some string')->shouldReturn('some string');
}
function its_presentValue_displays_invokable_objects_as_objects()
{
$invokable = new ObjectBehavior();
$invokable->setSpecificationSubject($this);
$this->presentValue($invokable)->shouldReturn('[obj:PhpSpec\Formatter\Presenter\StringPresenter]');
}
}
class WithMethod
{
function specMethod()
{
}
}
class WithStaticMethod
{
function specMethod()
{
}
}
class WithMagicInvoke
{
function __invoke()
{
}
}
class WithStaticMagicCall
{
static function __callStatic($method, $name)
{
}
}
class WithMagicCall
{
function __call($method, $name)
{
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace spec\PhpSpec\Formatter\Presenter;
use PhpSpec\ObjectBehavior;
use PhpSpec\Formatter\Presenter\Differ\Differ;
class TaggedPresenterSpec extends ObjectBehavior
{
function let(Differ $differ)
{
$this->beConstructedWith($differ);
}
function it_wraps_value_into_tags()
{
$this->presentValue('string')->shouldReturn('<value>"string"</value>');
}
function it_wraps_string_into_tags()
{
$this->presentString('string')->shouldReturn('<value>string</value>');
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace spec\PhpSpec\Formatter;
use PhpSpec\Console\IO;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use PhpSpec\Listener\StatisticsCollector;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ProgressFormatterSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter, IO $io, StatisticsCollector $stats)
{
$this->beConstructedWith($presenter, $io, $stats);
}
function it_is_an_event_subscriber()
{
$this->shouldHaveType('Symfony\Component\EventDispatcher\EventSubscriberInterface');
}
function it_outputs_progress_as_0_when_0_examples_have_run(ExampleEvent $event, IO $io, StatisticsCollector $stats)
{
$stats->getEventsCount()->willReturn(0);
$stats->getCountsHash()->willReturn(array(
'passed' => 0,
'pending' => 0,
'skipped' => 0,
'failed' => 0,
'broken' => 0,
));
$stats->getTotalSpecs()->willReturn(0);
$stats->getTotalSpecsCount()->willReturn(0);
$this->afterExample($event);
$expected = '/ skipped: 0% / pending: 0% / passed: 0% / failed: 0% / broken: 0% / 0 examples';
$io->writeTemp($expected)->shouldHaveBeenCalled();
}
function it_outputs_progress_as_0_when_0_examples_have_passed(ExampleEvent $event, IO $io, StatisticsCollector $stats)
{
$stats->getEventsCount()->willReturn(1);
$stats->getCountsHash()->willReturn(array(
'passed' => 1,
'pending' => 0,
'skipped' => 0,
'failed' => 0,
'broken' => 0,
));
$stats->getTotalSpecs()->willReturn(1);
$stats->getTotalSpecsCount()->willReturn(1);
$this->afterExample($event);
$expected = '/ skipped: 0% / pending: 0% / passed: 100% / failed: 0% / broken: 0% / 1 examples';
$io->writeTemp($expected)->shouldHaveBeenCalled();
}
function it_outputs_progress_as_100_when_1_of_3_examples_have_passed(ExampleEvent $event, IO $io, StatisticsCollector $stats)
{
$stats->getEventsCount()->willReturn(1);
$stats->getCountsHash()->willReturn(array(
'passed' => 1,
'pending' => 0,
'skipped' => 0,
'failed' => 0,
'broken' => 0,
));
$stats->getTotalSpecs()->willReturn(1);
$stats->getTotalSpecsCount()->willReturn(3);
$this->afterExample($event);
$expected = '/ skipped: 0% / pending: 0% / passed: 100% / failed: 0% / broken: 0% / 1 examples';
$io->writeTemp($expected)->shouldHaveBeenCalled();
}
function it_outputs_progress_as_33_when_3_of_3_examples_have_run_and_one_passed(ExampleEvent $event, IO $io, StatisticsCollector $stats)
{
$stats->getEventsCount()->willReturn(3);
$stats->getCountsHash()->willReturn(array(
'passed' => 1,
'pending' => 0,
'skipped' => 0,
'failed' => 2,
'broken' => 0,
));
$stats->getTotalSpecs()->willReturn(3);
$stats->getTotalSpecsCount()->willReturn(3);
$this->afterExample($event);
$expected = '/ skipped: 0% / pending: 0% / passed: 33% / failed: 66% / broken: 0% / 3 examples';
$io->writeTemp($expected)->shouldHaveBeenCalled();
}
}

View File

@@ -0,0 +1,148 @@
<?php
namespace spec\PhpSpec\Formatter;
use PhpSpec\Console\IO;
use PhpSpec\Event\SuiteEvent;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Event\SpecificationEvent;
use PhpSpec\Loader\Node\ExampleNode;
use PhpSpec\Loader\Node\SpecificationNode;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use PhpSpec\Listener\StatisticsCollector;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class TapFormatterSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter, IO $io, StatisticsCollector $stats)
{
$this->beConstructedWith($presenter, $io, $stats);
}
function it_is_an_event_subscriber()
{
$this->shouldHaveType('Symfony\Component\EventDispatcher\EventSubscriberInterface');
}
function it_outputs_version_on_beforesuite_event(SuiteEvent $event, IO $io)
{
$this->beforeSuite($event);
$expected = 'TAP version 13';
$io->writeln($expected)->shouldHaveBeenCalled();
}
function it_outputs_plan_on_aftersuite_event(SuiteEvent $suiteEvent, ExampleEvent $exampleEvent, ExampleNode $example, IO $io, StatisticsCollector $stats)
{
$stats->getEventsCount()->willReturn(3);
$exampleEvent->getExample()->willReturn($example);
$example->getTitle()->willReturn('foobar');
$exampleEvent->getResult()->willReturn(0);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->writeln('1..3')->shouldHaveBeenCalled();
}
function it_outputs_progress_on_afterexample_event(SpecificationEvent $specEvent, ExampleEvent $exampleEvent, ExampleNode $example, SpecificationNode $spec, IO $io, StatisticsCollector $stats)
{
$specEvent->getSpecification()->willReturn($spec);
$exampleEvent->getExample()->willReturn($example);
$exampleEvent->getResult()->willReturn(ExampleEvent::PASSED);
$example->getTitle()->willReturn('it foobar');
$spec->getTitle()->willReturn('spec1');
$this->beforeSpecification($specEvent);
$this->afterExample($exampleEvent);
$example->getTitle()->willReturn('its foobar');
$spec->getTitle()->willReturn('spec2');
$this->beforeSpecification($specEvent);
$this->afterExample($exampleEvent);
$expected1 = 'ok 1 - spec1: foobar';
$expected2 = 'ok 2 - spec2: foobar';
$io->writeln($expected1)->shouldHaveBeenCalled();
$io->writeln($expected2)->shouldHaveBeenCalled();
}
function it_outputs_failure_progress_on_afterexample_event(SpecificationEvent $specEvent, ExampleEvent $exampleEvent, ExampleNode $example, SpecificationNode $spec, IO $io, StatisticsCollector $stats)
{
$specEvent->getSpecification()->willReturn($spec);
$exampleEvent->getExample()->willReturn($example);
$example->getTitle()->willReturn('foobar');
$exampleEvent->getResult()->willReturn(ExampleEvent::FAILED);
$exampleEvent->getException()->willReturn(new \Exception('Something failed.'));
$spec->getTitle()->willReturn('spec1');
$this->beforeSpecification($specEvent);
$this->afterExample($exampleEvent);
$expected = "not ok 1 - spec1: foobar\n ---\n message: 'Something failed.'\n severity: fail\n ...";
$io->writeln($expected)->shouldHaveBeenCalled();
}
function it_outputs_skip_progress_on_afterexample_event(SpecificationEvent $specEvent, ExampleEvent $exampleEvent, ExampleNode $example, SpecificationNode $spec, IO $io, StatisticsCollector $stats)
{
$specEvent->getSpecification()->willReturn($spec);
$exampleEvent->getExample()->willReturn($example);
$example->getTitle()->willReturn('foobar');
$exampleEvent->getResult()->willReturn(ExampleEvent::SKIPPED);
$exampleEvent->getException()->willReturn(new \Exception('no reason'));
$spec->getTitle()->willReturn('spec1');
$this->beforeSpecification($specEvent);
$this->afterExample($exampleEvent);
$expected = 'ok 1 - spec1: foobar # SKIP no reason';
$io->writeln($expected)->shouldHaveBeenCalled();
}
function it_outputs_todo_progress_on_afterexample_event(SpecificationEvent $specEvent, ExampleEvent $exampleEvent, ExampleNode $example, SpecificationNode $spec, IO $io, StatisticsCollector $stats)
{
$specEvent->getSpecification()->willReturn($spec);
$exampleEvent->getExample()->willReturn($example);
$example->getTitle()->willReturn('foobar');
$exampleEvent->getResult()->willReturn(ExampleEvent::PENDING);
$exampleEvent->getException()->willReturn(new \Exception("no\nreason"));
$spec->getTitle()->willReturn('spec1');
$this->beforeSpecification($specEvent);
$this->afterExample($exampleEvent);
$expected = "not ok 1 - spec1: foobar # TODO no / reason\n ---\n severity: todo\n ...";
$io->writeln($expected)->shouldHaveBeenCalled();
}
function it_outputs_broken_progress_on_afterexample_event(SpecificationEvent $specEvent, ExampleEvent $exampleEvent, ExampleNode $example, SpecificationNode $spec, IO $io, StatisticsCollector $stats)
{
$specEvent->getSpecification()->willReturn($spec);
$exampleEvent->getExample()->willReturn($example);
$example->getTitle()->willReturn('foobar');
$exampleEvent->getResult()->willReturn(ExampleEvent::BROKEN);
$exampleEvent->getException()->willReturn(new \Exception("Something broke's.\nIt hurts."));
$spec->getTitle()->willReturn('spec1');
$this->beforeSpecification($specEvent);
$this->afterExample($exampleEvent);
$expected = "not ok 1 - spec1: foobar\n ---\n message: \"Something broke's.\\nIt hurts.\"\n severity: fail\n ...";
$io->writeln($expected)->shouldHaveBeenCalled();
}
function it_outputs_undefined_progress_on_afterexample_event(SpecificationEvent $specEvent, ExampleEvent $exampleEvent, ExampleNode $example, SpecificationNode $spec, IO $io, StatisticsCollector $stats)
{
$specEvent->getSpecification()->willReturn($spec);
$exampleEvent->getExample()->willReturn($example);
$example->getTitle()->willReturn('foobar');
$exampleEvent->getResult()->willReturn(999);
$spec->getTitle()->willReturn('spec1');
$this->beforeSpecification($specEvent);
$this->afterExample($exampleEvent);
$expected = "not ok 1 - spec1: foobar\n ---\n message: 'The example result type was unknown to formatter'\n severity: fail\n ...";
$io->writeln($expected)->shouldHaveBeenCalled();
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace spec\PhpSpec\Listener;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Console\IO;
use PhpSpec\Locator\ResourceManager;
use PhpSpec\CodeGenerator\GeneratorManager;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Event\SuiteEvent;
use PhpSpec\Exception\Fracture\ClassNotFoundException as PhpSpecClassException;
use Prophecy\Exception\Doubler\ClassNotFoundException as ProphecyClassException;
class ClassNotFoundListenerSpec extends ObjectBehavior
{
function let(IO $io, ResourceManager $resourceManager, GeneratorManager $generatorManager,
SuiteEvent $suiteEvent, ExampleEvent $exampleEvent)
{
$io->writeln(Argument::any())->willReturn();
$io->askConfirmation(Argument::any())->willReturn();
$this->beConstructedWith($io, $resourceManager, $generatorManager);
}
function it_does_not_prompt_for_class_generation_if_no_exception_was_thrown($exampleEvent, $suiteEvent, $io)
{
$io->isCodeGenerationEnabled()->willReturn(true);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotBeenCalled();
}
function it_does_not_prompt_for_class_generation_if_non_class_exception_was_thrown($exampleEvent, $suiteEvent, $io, \InvalidArgumentException $exception)
{
$exampleEvent->getException()->willReturn($exception);
$io->isCodeGenerationEnabled()->willReturn(true);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotBeenCalled();
}
function it_prompts_for_class_generation_if_prophecy_classnotfoundexception_was_thrown_and_input_is_interactive($exampleEvent, $suiteEvent, $io, ProphecyClassException $exception)
{
$exampleEvent->getException()->willReturn($exception);
$io->isCodeGenerationEnabled()->willReturn(true);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldHaveBeenCalled();
}
function it_prompts_for_method_generation_if_phpspec_classnotfoundexception_was_thrown_and_input_is_interactive($exampleEvent, $suiteEvent, $io, PhpspecClassException $exception)
{
$exampleEvent->getException()->willReturn($exception);
$io->isCodeGenerationEnabled()->willReturn(true);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldHaveBeenCalled();
}
function it_does_not_prompt_for_class_generation_if_input_is_not_interactive($exampleEvent, $suiteEvent, $io, PhpspecClassException $exception)
{
$exampleEvent->getException()->willReturn($exception);
$io->isCodeGenerationEnabled()->willReturn(false);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotBeenCalled();
}
}

View File

@@ -0,0 +1,162 @@
<?php
namespace spec\PhpSpec\Listener;
use PhpSpec\CodeGenerator\GeneratorManager;
use PhpSpec\Console\IO;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Event\SuiteEvent;
use PhpSpec\Exception\Locator\ResourceCreationException;
use PhpSpec\Locator\ResourceInterface;
use PhpSpec\Locator\ResourceManager;
use PhpSpec\Locator\ResourceManagerInterface;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Prophecy\Doubler\DoubleInterface;
use Prophecy\Exception\Doubler\MethodNotFoundException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
class CollaboratorMethodNotFoundListenerSpec extends ObjectBehavior
{
function let(
IO $io, ResourceManagerInterface $resources, ExampleEvent $event,
MethodNotFoundException $exception, ResourceInterface $resource, GeneratorManager $generator
)
{
$this->beConstructedWith($io, $resources, $generator);
$event->getException()->willReturn($exception);
$io->isCodeGenerationEnabled()->willReturn(true);
$io->askConfirmation(Argument::any())->willReturn(false);
$resources->createResource(Argument::any())->willReturn($resource);
$exception->getArguments()->willReturn(array());
}
function it_is_an_event_subscriber()
{
$this->shouldHaveType('Symfony\Component\EventDispatcher\EventSubscriberInterface');
}
function it_listens_to_afterexample_events()
{
$this->getSubscribedEvents()->shouldReturn(array(
'afterExample' => array('afterExample', 10),
'afterSuite' => array('afterSuite', -10)
));
}
function it_does_not_prompt_when_no_exception_is_thrown(IO $io, ExampleEvent $event, SuiteEvent $suiteEvent)
{
$event->getException()->willReturn(null);
$this->afterExample($event);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_prompts_the_user_when_a_prophecy_method_exception_is_thrown(
IO $io, ExampleEvent $event, SuiteEvent $suiteEvent, MethodNotFoundException $exception
)
{
$exception->getClassname()->willReturn('spec\PhpSpec\Listener\DoubleOfInterface');
$exception->getMethodName()->willReturn('aMethod');
$this->afterExample($event);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldHaveBeenCalled();
}
function it_does_not_prompt_when_wrong_exception_is_thrown(IO $io, ExampleEvent $event, SuiteEvent $suiteEvent)
{
$event->getException()->willReturn(new RuntimeException());
$this->afterExample($event);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_when_collaborator_is_not_an_interface(
IO $io, ExampleEvent $event, SuiteEvent $suiteEvent, MethodNotFoundException $exception
)
{
$exception->getClassname()->willReturn('spec\PhpSpec\Listener\DoubleOfStdClass');
$exception->getMethodName()->willReturn('aMethod');
$this->afterExample($event);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_when_code_generation_is_disabled(
IO $io, ExampleEvent $event, SuiteEvent $suiteEvent, MethodNotFoundException $exception
)
{
$io->isCodeGenerationEnabled()->willReturn(false);
$exception->getClassname()->willReturn('spec\PhpSpec\Listener\DoubleOfInterface');
$exception->getMethodName()->willReturn('aMethod');
$this->afterExample($event);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_if_it_cannot_generate_the_resource(
IO $io, ResourceManager $resources, ExampleEvent $event, SuiteEvent $suiteEvent, MethodNotFoundException $exception
)
{
$resources->createResource(Argument::any())->willThrow(new ResourceCreationException());
$exception->getClassname()->willReturn('spec\PhpSpec\Listener\DoubleOfInterface');
$exception->getMethodName()->willReturn('aMethod');
$this->afterExample($event);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_generates_the_method_signature_when_user_says_yes_at_prompt(
IO $io, ExampleEvent $event, SuiteEvent $suiteEvent, MethodNotFoundException $exception,
ResourceInterface $resource, GeneratorManager $generator
)
{
$io->askConfirmation(Argument::any())->willReturn(true);
$exception->getClassname()->willReturn('spec\PhpSpec\Listener\DoubleOfInterface');
$exception->getMethodName()->willReturn('aMethod');
$this->afterExample($event);
$this->afterSuite($suiteEvent);
$generator->generate($resource, 'method-signature', Argument::any())->shouldHaveBeenCalled();
}
function it_marks_the_suite_as_being_worth_rerunning_when_generation_happens(
IO $io, ExampleEvent $event, SuiteEvent $suiteEvent, MethodNotFoundException $exception
)
{
$io->askConfirmation(Argument::any())->willReturn(true);
$exception->getClassname()->willReturn('spec\PhpSpec\Listener\DoubleOfInterface');
$exception->getMethodName()->willReturn('aMethod');
$this->afterExample($event);
$this->afterSuite($suiteEvent);
$suiteEvent->markAsWorthRerunning()->shouldHaveBeenCalled();
}
}
interface ExampleInterface {}
class DoubleOfInterface extends \stdClass implements ExampleInterface, DoubleInterface {}
class DoubleOfStdClass extends \stdClass implements DoubleInterface {}

View File

@@ -0,0 +1,134 @@
<?php
namespace spec\PhpSpec\Listener;
use PhpSpec\CodeGenerator\GeneratorManager;
use PhpSpec\Console\IO;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Event\SuiteEvent;
use PhpSpec\Exception\Fracture\CollaboratorNotFoundException;
use PhpSpec\Locator\ResourceInterface;
use PhpSpec\Locator\ResourceManagerInterface;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CollaboratorNotFoundListenerSpec extends ObjectBehavior
{
function let(
IO $io, CollaboratorNotFoundException $exception, ExampleEvent $exampleEvent,
ResourceManagerInterface $resources, GeneratorManager $generator, ResourceInterface $resource
)
{
$this->beConstructedWith($io, $resources, $generator);
$resources->createResource(Argument::any())->willReturn($resource);
$resource->getSpecNamespace()->willReturn('spec');
$exampleEvent->getException()->willReturn($exception);
$exception->getCollaboratorName()->willReturn('Example\ExampleClass');
$io->isCodeGenerationEnabled()->willReturn(true);
$io->askConfirmation(Argument::any())->willReturn(false);
$io->writeln(Argument::any())->willReturn(null);
}
function it_listens_to_afterexample_and_aftersuite_events()
{
$this->getSubscribedEvents()->shouldReturn(array(
'afterExample' => array('afterExample', 10),
'afterSuite' => array('afterSuite', -10)
));
}
function it_prompts_to_generate_missing_collaborator(
IO $io, ExampleEvent $exampleEvent, SuiteEvent $suiteEvent
)
{
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(
'Would you like me to generate an interface `Example\ExampleClass` for you?'
)->shouldHaveBeenCalled();
}
function it_does_not_prompt_to_generate_when_there_was_no_exception(
IO $io, ExampleEvent $exampleEvent, SuiteEvent $suiteEvent
)
{
$exampleEvent->getException()->willReturn(null);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_to_generate_when_there_was_an_exception_of_the_wrong_type(
IO $io, ExampleEvent $exampleEvent, SuiteEvent $suiteEvent, \InvalidArgumentException $otherException
)
{
$exampleEvent->getException()->willReturn($otherException);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_when_code_generation_is_disabled(
IO $io, ExampleEvent $exampleEvent, SuiteEvent $suiteEvent
)
{
$io->isCodeGenerationEnabled()->willReturn(false);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_when_collaborator_is_in_spec_namespace(
IO $io, ExampleEvent $exampleEvent, SuiteEvent $suiteEvent, CollaboratorNotFoundException $exception
)
{
$exception->getCollaboratorName()->willReturn('spec\Example\ExampleClass');
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_generates_interface_when_prompt_is_answered_with_yes(
IO $io, ExampleEvent $exampleEvent, SuiteEvent $suiteEvent,
GeneratorManager $generator, ResourceInterface $resource
)
{
$io->askConfirmation(
'Would you like me to generate an interface `Example\ExampleClass` for you?'
)->willReturn(true);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$generator->generate($resource, 'interface')->shouldHaveBeenCalled();
$suiteEvent->markAsWorthRerunning()->shouldHaveBeenCalled();
}
function it_does_not_generate_interface_when_prompt_is_answered_with_no(
IO $io, ExampleEvent $exampleEvent, SuiteEvent $suiteEvent,
GeneratorManager $generator
)
{
$io->askConfirmation(
'Would you like me to generate an interface `Example\ExampleClass` for you?'
)->willReturn(false);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$generator->generate(Argument::cetera())->shouldNotHaveBeenCalled();
$suiteEvent->markAsWorthRerunning()->shouldNotHaveBeenCalled();
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace spec\PhpSpec\Listener;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Console\IO;
use PhpSpec\Locator\ResourceManager;
use PhpSpec\CodeGenerator\GeneratorManager;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Event\SuiteEvent;
use PhpSpec\Exception\Fracture\MethodNotFoundException;
class MethodNotFoundListenerSpec extends ObjectBehavior
{
function let(IO $io, ResourceManager $resourceManager, GeneratorManager $generatorManager,
SuiteEvent $suiteEvent, ExampleEvent $exampleEvent)
{
$io->writeln(Argument::any())->willReturn();
$io->askConfirmation(Argument::any())->willReturn();
$this->beConstructedWith($io, $resourceManager, $generatorManager);
}
function it_does_not_prompt_for_method_generation_if_no_exception_was_thrown($exampleEvent, $suiteEvent, $io)
{
$io->isCodeGenerationEnabled()->willReturn(true);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotBeenCalled();
}
function it_does_not_prompt_for_method_generation_if_non_methodnotfoundexception_was_thrown($exampleEvent, $suiteEvent, $io, \InvalidArgumentException $exception)
{
$exampleEvent->getException()->willReturn($exception);
$io->isCodeGenerationEnabled()->willReturn(true);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotBeenCalled();
}
function it_prompts_for_method_generation_if_methodnotfoundexception_was_thrown_and_input_is_interactive($exampleEvent, $suiteEvent, $io, MethodNotFoundException $exception)
{
$exampleEvent->getException()->willReturn($exception);
$io->isCodeGenerationEnabled()->willReturn(true);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldHaveBeenCalled();
}
function it_does_not_prompt_for_method_generation_if_input_is_not_interactive($exampleEvent, $suiteEvent, $io, MethodNotFoundException $exception)
{
$exampleEvent->getException()->willReturn($exception);
$io->isCodeGenerationEnabled()->willReturn(false);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotBeenCalled();
}
}

View File

@@ -0,0 +1,209 @@
<?php
namespace spec\PhpSpec\Listener;
use PhpSpec\CodeGenerator\GeneratorManager;
use PhpSpec\Console\IO;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Event\MethodCallEvent;
use PhpSpec\Event\SuiteEvent;
use PhpSpec\Exception\Example\NotEqualException;
use PhpSpec\Locator\ResourceInterface;
use PhpSpec\Locator\ResourceManager;
use PhpSpec\ObjectBehavior;
use PhpSpec\Util\MethodAnalyser;
use Prophecy\Argument;
class MethodReturnedNullListenerSpec extends ObjectBehavior
{
function let(
IO $io, ResourceManager $resourceManager, GeneratorManager $generatorManager,
ExampleEvent $exampleEvent, NotEqualException $notEqualException, MethodAnalyser $methodAnalyser
) {
$this->beConstructedWith($io, $resourceManager, $generatorManager, $methodAnalyser);
$exampleEvent->getException()->willReturn($notEqualException);
$notEqualException->getActual()->willReturn(null);
$notEqualException->getExpected()->willReturn(100);
$io->isCodeGenerationEnabled()->willReturn(true);
$io->askConfirmation(Argument::any())->willReturn(false);
$io->isFakingEnabled()->willReturn(true);
$methodAnalyser->methodIsEmpty(Argument::cetera())->willReturn(true);
$methodAnalyser->getMethodOwnerName(Argument::cetera())->willReturn('Foo');;
}
function it_is_an_event_listener()
{
$this->shouldHaveType('Symfony\Component\EventDispatcher\EventSubscriberInterface');
}
function it_listens_to_examples_to_spot_failures()
{
$this->getSubscribedEvents()->shouldHaveKey('afterExample');
}
function it_listens_to_suites_to_know_when_to_prompt()
{
$this->getSubscribedEvents()->shouldHaveKey('afterSuite');
}
function it_listens_to_method_calls_to_see_what_has_failed()
{
$this->getSubscribedEvents()->shouldHaveKey('afterMethodCall');
}
function it_does_not_prompt_when_wrong_type_of_exception_is_thrown(
MethodCallEvent $methodCallEvent, ExampleEvent $exampleEvent, IO $io, SuiteEvent $event
) {
$exampleEvent->getException()->willReturn(new \Exception());
$this->afterMethodCall($methodCallEvent);
$this->afterExample($exampleEvent);
$this->afterSuite($event);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_when_actual_value_is_not_null(
MethodCallEvent $methodCallEvent, ExampleEvent $exampleEvent, NotEqualException $notEqualException, IO $io, SuiteEvent $event
) {
$exampleEvent->getException()->willReturn($notEqualException);
$notEqualException->getActual()->willReturn(90);
$notEqualException->getExpected()->willReturn(100);
$this->afterMethodCall($methodCallEvent);
$this->afterExample($exampleEvent);
$this->afterSuite($event);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_when_expected_value_is_an_object(
MethodCallEvent $methodCallEvent, ExampleEvent $exampleEvent, NotEqualException $notEqualException, IO $io, SuiteEvent $event
) {
$exampleEvent->getException()->willReturn($notEqualException);
$notEqualException->getActual()->willReturn(null);
$notEqualException->getExpected()->willReturn(new \DateTime());
$this->afterMethodCall($methodCallEvent);
$this->afterExample($exampleEvent);
$this->afterSuite($event);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_if_no_method_was_called_beforehand(ExampleEvent $exampleEvent, IO $io, SuiteEvent $event)
{
$this->afterExample($exampleEvent);
$this->afterSuite($event);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_when_there_is_a_problem_creating_the_resource(
MethodCallEvent $methodCallEvent, ExampleEvent $exampleEvent, IO $io, ResourceManager $resourceManager, SuiteEvent $event
) {
$resourceManager->createResource(Argument::any())->willThrow(new \RuntimeException());
$this->afterMethodCall($methodCallEvent);
$this->afterExample($exampleEvent);
$this->afterSuite($event);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_when_input_is_not_interactive(
MethodCallEvent $methodCallEvent, ExampleEvent $exampleEvent, IO $io, SuiteEvent $event
) {
$io->isCodeGenerationEnabled()->willReturn(false);
$this->afterMethodCall($methodCallEvent);
$this->afterExample($exampleEvent);
$this->afterSuite($event);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_when_method_is_not_empty(
MethodCallEvent $methodCallEvent, ExampleEvent $exampleEvent, IO $io, MethodAnalyser $methodAnalyser, SuiteEvent $event
) {
$methodCallEvent->getMethod()->willReturn('myMethod');
$methodCallEvent->getSubject()->willReturn(new \DateTime());
$methodAnalyser->methodIsEmpty('DateTime', 'myMethod')->willReturn(false);
$this->afterMethodCall($methodCallEvent);
$this->afterExample($exampleEvent);
$this->afterSuite($event);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_when_multiple_contradictory_examples_are_found(
MethodCallEvent $methodCallEvent, ExampleEvent $exampleEvent, NotEqualException $notEqualException, IO $io,
ExampleEvent $exampleEvent2, NotEqualException $notEqualException2, SuiteEvent $event
) {
$exampleEvent->getException()->willReturn($notEqualException);
$exampleEvent2->getException()->willReturn($notEqualException2);
$notEqualException->getActual()->willReturn(null);
$notEqualException2->getActual()->willReturn(null);
$notEqualException->getExpected()->willReturn('foo');
$notEqualException2->getExpected()->willReturn('bar');
$this->afterMethodCall($methodCallEvent);
$this->afterExample($exampleEvent);
$this->afterMethodCall($methodCallEvent);
$this->afterExample($exampleEvent2);
$this->afterSuite($event);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_does_not_prompt_when_io_has_faking_disabled(
MethodCallEvent $methodCallEvent, ExampleEvent $exampleEvent, IO $io, SuiteEvent $event
) {
$io->isFakingEnabled()->willReturn(false);
$this->afterMethodCall($methodCallEvent);
$this->afterExample($exampleEvent);
$this->afterSuite($event);
$io->askConfirmation(Argument::any())->shouldNotHaveBeenCalled();
}
function it_prompts_when_correct_type_of_exception_is_thrown(
MethodCallEvent $methodCallEvent, ExampleEvent $exampleEvent, IO $io, SuiteEvent $event
) {
$this->afterMethodCall($methodCallEvent);
$this->afterExample($exampleEvent);
$this->afterSuite($event);
$io->askConfirmation(Argument::any())->shouldHaveBeenCalled();
}
function it_invokes_method_body_generation_when_prompt_is_answered_yes(
MethodCallEvent $methodCallEvent, ExampleEvent $exampleEvent, IO $io,
GeneratorManager $generatorManager, ResourceManager $resourceManager, ResourceInterface $resource, SuiteEvent $event
) {
$io->askConfirmation(Argument::any())->willReturn(true);
$resourceManager->createResource(Argument::any())->willReturn($resource);
$methodCallEvent->getSubject()->willReturn(new \StdClass());
$methodCallEvent->getMethod()->willReturn('myMethod');
$this->afterMethodCall($methodCallEvent);
$this->afterExample($exampleEvent);
$this->afterSuite($event);
$generatorManager->generate($resource, 'returnConstant', array('method' => 'myMethod', 'expected' => 100))
->shouldHaveBeenCalled();
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace spec\PhpSpec\Listener;
use PhpSpec\CodeGenerator\GeneratorManager;
use PhpSpec\Console\IO;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Event\SuiteEvent;
use PhpSpec\Exception\Fracture\NamedConstructorNotFoundException;
use PhpSpec\Locator\ResourceManager;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class NamedConstructorNotFoundListenerSpec extends ObjectBehavior
{
function let(IO $io, ResourceManager $resourceManager, GeneratorManager $generatorManager,
SuiteEvent $suiteEvent, ExampleEvent $exampleEvent)
{
$io->writeln(Argument::any())->willReturn();
$io->askConfirmation(Argument::any())->willReturn();
$this->beConstructedWith($io, $resourceManager, $generatorManager);
}
function it_does_not_prompt_for_method_generation_if_no_exception_was_thrown($exampleEvent, $suiteEvent, $io)
{
$io->isCodeGenerationEnabled()->willReturn(true);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotBeenCalled();
}
function it_does_not_prompt_for_method_generation_if_non_namedconstructornotfoundexception_was_thrown($exampleEvent, $suiteEvent, $io, \InvalidArgumentException $exception)
{
$exampleEvent->getException()->willReturn($exception);
$io->isCodeGenerationEnabled()->willReturn(true);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotBeenCalled();
}
function it_prompts_for_method_generation_if_namedconstructornotfoundexception_was_thrown_and_input_is_interactive($exampleEvent, $suiteEvent, $io, NamedConstructorNotFoundException $exception)
{
$exampleEvent->getException()->willReturn($exception);
$io->isCodeGenerationEnabled()->willReturn(true);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldHaveBeenCalled();
}
function it_does_not_prompt_for_method_generation_if_input_is_not_interactive($exampleEvent, $suiteEvent, $io, NamedConstructorNotFoundException $exception)
{
$exampleEvent->getException()->willReturn($exception);
$io->isCodeGenerationEnabled()->willReturn(false);
$this->afterExample($exampleEvent);
$this->afterSuite($suiteEvent);
$io->askConfirmation(Argument::any())->shouldNotBeenCalled();
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace spec\PhpSpec\Listener;
use PhpSpec\Event\SuiteEvent;
use PhpSpec\ObjectBehavior;
use PhpSpec\Process\ReRunner;
use Prophecy\Argument;
class RerunListenerSpec extends ObjectBehavior
{
function let(ReRunner $reRunner)
{
$this->beConstructedWith($reRunner);
}
function it_subscribes_to_aftersuite()
{
$this->shouldHaveType('Symfony\Component\EventDispatcher\EventSubscriberInterface');
$this->getSubscribedEvents()->shouldHaveKey('afterSuite');
}
function it_does_not_tell_the_rerunner_to_rerun_if_it_is_not_worth_doing_so(SuiteEvent $suiteEvent, ReRunner $reRunner)
{
$suiteEvent->isWorthRerunning()->willReturn(false);
$this->afterSuite($suiteEvent);
$reRunner->reRunSuite()->shouldNotHaveBeenCalled();
}
function it_tells_the_rerunner_to_rerun_if_it_is_worth_doing_so(SuiteEvent $suiteEvent, ReRunner $reRunner)
{
$suiteEvent->isWorthRerunning()->willReturn(true);
$this->afterSuite($suiteEvent);
$reRunner->reRunSuite()->shouldHaveBeenCalled();
}
}

View File

@@ -0,0 +1,113 @@
<?php
namespace spec\PhpSpec\Listener;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Event\SpecificationEvent;
use PhpSpec\Event\SuiteEvent;
use PhpSpec\Loader\Node\SpecificationNode;
use PhpSpec\Loader\Suite;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class StatisticsCollectorSpec extends ObjectBehavior
{
function let(ExampleEvent $failingExample, ExampleEvent $passingExample)
{
$failingExample->getResult()->willReturn(ExampleEvent::FAILED);
$passingExample->getResult()->willReturn(ExampleEvent::PASSED);
}
function it_is_an_event_listener()
{
$this->shouldHaveType('Symfony\Component\EventDispatcher\EventSubscriberInterface');
}
function it_listens_to_stats_generating_events()
{
$subscribedEvents = $this->getSubscribedEvents();
$subscribedEvents->shouldHaveKey('afterExample');
$subscribedEvents->shouldHaveKey('afterSpecification');
$subscribedEvents->shouldHaveKey('beforeSuite');
}
function it_knows_no_specs_have_run_initially()
{
$this->getTotalSpecs()->shouldReturn(0);
}
function it_counts_how_many_specs_have_run(SpecificationEvent $specEvent1, SpecificationEvent $specEvent2)
{
$this->afterSpecification($specEvent1);
$this->afterSpecification($specEvent2);
$this->getTotalSpecs()->shouldReturn(2);
}
function it_knows_no_examples_have_run_initially()
{
$this->getEventsCount()->shouldReturn(0);
}
function it_counts_how_many_examples_have_run(ExampleEvent $failingExample, ExampleEvent $passingExample)
{
$this->afterExample($passingExample);
$this->afterExample($failingExample);
$this->getEventsCount()->shouldReturn(2);
}
function it_logs_all_example_events(ExampleEvent $failingExample, ExampleEvent $passingExample)
{
$this->afterExample($passingExample);
$this->afterExample($failingExample);
$this->getAllEvents()->shouldReturn(array(
$passingExample,
$failingExample
));
}
function it_logs_all_example_events_by_type(ExampleEvent $failingExample, ExampleEvent $passingExample)
{
$this->afterExample($passingExample);
$this->afterExample($failingExample);
$this->getPassedEvents()->shouldReturn(array($passingExample));
}
function it_counts_example_results_by_type(ExampleEvent $failingExample, ExampleEvent $passingExample)
{
$this->afterExample($passingExample);
$this->afterExample($failingExample);
$this->getCountsHash()->shouldReturn(
array(
'passed' => 1,
'pending' => 0,
'skipped' => 0,
'failed' => 1,
'broken' => 0,
)
);
}
function it_returns_the_worst_result_as_the_global_result(ExampleEvent $failingExample, ExampleEvent $passingExample)
{
$this->afterExample($passingExample);
$this->afterExample($failingExample);
$this->getGlobalResult()->shouldReturn(ExampleEvent::FAILED);
}
function it_records_how_many_specs_are_in_the_suite(SuiteEvent $suiteEvent, Suite $suite, SpecificationNode $spec)
{
$suiteEvent->getSuite()->willReturn($suite);
$suite->getSpecifications()->willReturn(array($spec));
$this->beforeSuite($suiteEvent);
$this->getTotalSpecsCount()->shouldReturn(1);
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace spec\PhpSpec\Listener;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Console\IO;
class StopOnFailureListenerSpec extends ObjectBehavior
{
function let(IO $io)
{
$io->isStopOnFailureEnabled()->willReturn(false);
$this->beConstructedWith($io);
}
function it_is_an_event_subscriber()
{
$this->shouldHaveType('Symfony\Component\EventDispatcher\EventSubscriberInterface');
}
function it_does_not_throw_any_exception_when_example_succeeds(ExampleEvent $event)
{
$event->getResult()->willReturn(ExampleEvent::PASSED);
$this->afterExample($event);
}
function it_does_not_throw_any_exception_for_unimplemented_examples(ExampleEvent $event)
{
$event->getResult()->willReturn(ExampleEvent::PENDING);
$this->afterExample($event);
}
function it_throws_an_exception_when_an_example_fails_and_option_is_set(ExampleEvent $event, $io)
{
$io->isStopOnFailureEnabled()->willReturn(true);
$event->getResult()->willReturn(ExampleEvent::FAILED);
$this->shouldThrow('\PhpSpec\Exception\Example\StopOnFailureException')->duringAfterExample($event);
}
function it_does_not_throw_an_exception_when_an_example_fails_and_option_is_not_set(ExampleEvent $event)
{
$event->getResult()->willReturn(ExampleEvent::FAILED);
$this->afterExample($event);
}
function it_throws_an_exception_when_an_example_breaks_and_option_is_set(ExampleEvent $event, $io)
{
$io->isStopOnFailureEnabled()->willReturn(true);
$event->getResult()->willReturn(ExampleEvent::BROKEN);
$this->shouldThrow('\PhpSpec\Exception\Example\StopOnFailureException')->duringAfterExample($event);
}
function it_does_not_throw_an_exception_when_an_example_breaks_and_option_is_not_set(ExampleEvent $event)
{
$event->getResult()->willReturn(ExampleEvent::BROKEN);
$this->afterExample($event);
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace spec\PhpSpec\Loader\Node;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Loader\Node\SpecificationNode;
use ReflectionFunctionAbstract;
class ExampleNodeSpec extends ObjectBehavior
{
function let(ReflectionFunctionAbstract $function)
{
$this->beConstructedWith('example node', $function);
}
function it_provides_a_link_to_title()
{
$this->getTitle()->shouldReturn('example node');
}
function it_provides_a_link_to_function($function)
{
$this->getFunctionReflection()->shouldReturn($function);
}
function it_provides_a_link_to_specification(SpecificationNode $specification)
{
$this->setSpecification($specification);
$this->getSpecification()->shouldReturn($specification);
}
function it_is_not_pending_by_default()
{
$this->isPending()->shouldReturn(false);
}
function it_is_pending_after_marked_as_pending_with_no_args()
{
$this->markAsPending();
$this->isPending()->shouldReturn(true);
}
function it_is_pending_after_marked_as_pending_with_true()
{
$this->markAsPending(true);
$this->isPending()->shouldReturn(true);
}
function it_is_not_pending_after_marked_as_pending_with_false()
{
$this->markAsPending(false);
$this->isPending()->shouldReturn(false);
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace spec\PhpSpec\Loader\Node;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Locator\ResourceInterface;
use PhpSpec\Loader\Node\ExampleNode;
use PhpSpec\Loader\Suite;
use ReflectionClass;
class SpecificationNodeSpec extends ObjectBehavior
{
public function let(ReflectionClass $class, ResourceInterface $resource)
{
$this->beConstructedWith('specification node', $class, $resource);
}
function it_is_countable()
{
$this->shouldImplement('Countable');
}
function it_provides_a_link_to_title()
{
$this->getTitle()->shouldReturn('specification node');
}
function it_provides_a_link_to_class($class)
{
$this->getClassReflection()->shouldReturn($class);
}
function it_provides_a_link_to_resource($resource)
{
$this->getResource()->shouldReturn($resource);
}
function it_provides_a_link_to_suite(Suite $suite)
{
$this->setSuite($suite);
$this->getSuite()->shouldReturn($suite);
}
function it_provides_a_link_to_examples(ExampleNode $example)
{
$this->addExample($example);
$this->addExample($example);
$this->addExample($example);
$this->getExamples()->shouldReturn(array($example, $example, $example));
}
function it_provides_a_count_of_examples(ExampleNode $example)
{
$this->addExample($example);
$this->addExample($example);
$this->addExample($example);
$this->count()->shouldReturn(3);
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace spec\PhpSpec\Loader;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Loader\Node\SpecificationNode;
class SuiteSpec extends ObjectBehavior
{
function it_is_countable()
{
$this->shouldImplement('Countable');
}
function it_provides_a_link_to_specifications(SpecificationNode $spec)
{
$this->addSpecification($spec);
$this->addSpecification($spec);
$this->addSpecification($spec);
$this->getSpecifications()->shouldReturn(array($spec, $spec, $spec));
}
function it_provides_a_count_of_examples(SpecificationNode $spec)
{
$this->addSpecification($spec);
$this->addSpecification($spec);
$this->addSpecification($spec);
$spec->count(Argument::any())->willReturn(5);
$this->count()->shouldReturn(15);
}
}

View File

@@ -0,0 +1,502 @@
<?php
namespace spec\PhpSpec\Locator\PSR0;
use PhpSpec\ObjectBehavior;
use PhpSpec\Util\Filesystem;
use SplFileInfo;
class PSR0LocatorSpec extends ObjectBehavior
{
private $srcPath;
private $specPath;
function let(Filesystem $fs)
{
$this->srcPath = realpath(__DIR__.'/../../../../src');
$this->specPath = realpath(__DIR__.'/../../../../');
}
function it_is_a_locator()
{
$this->shouldBeAnInstanceOf('PhpSpec\Locator\ResourceLocatorInterface');
}
function its_priority_is_zero()
{
$this->getPriority()->shouldReturn(0);
}
function it_generates_fullSrcPath_from_srcPath_plus_namespace()
{
$this->beConstructedWith('Cust\Ns', 'spec', dirname(__DIR__), __DIR__);
$this->getFullSrcPath()->shouldReturn(
dirname(__DIR__).DIRECTORY_SEPARATOR.'Cust'.DIRECTORY_SEPARATOR.'Ns'.DIRECTORY_SEPARATOR
);
}
function it_generates_fullSrcPath_from_srcPath_plus_namespace_cutting_psr4_prefix()
{
$this->beConstructedWith('psr4\prefix\Cust\Ns', 'spec', dirname(__DIR__), __DIR__, null, 'psr4\prefix');
$this->getFullSrcPath()->shouldReturn(
dirname(__DIR__).DIRECTORY_SEPARATOR.'Cust'.DIRECTORY_SEPARATOR.'Ns'.DIRECTORY_SEPARATOR
);
}
function it_generates_proper_fullSrcPath_even_from_empty_namespace()
{
$this->beConstructedWith('', 'spec', dirname(__DIR__), __DIR__);
$this->getFullSrcPath()->shouldReturn(dirname(__DIR__).DIRECTORY_SEPARATOR);
}
function it_generates_fullSpecPath_from_specPath_plus_namespace()
{
$this->beConstructedWith('C\N', 'spec', dirname(__DIR__), __DIR__);
$this->getFullSpecPath()->shouldReturn(
__DIR__.DIRECTORY_SEPARATOR.'spec'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'N'.DIRECTORY_SEPARATOR
);
}
function it_generates_fullSpecPath_from_specPath_plus_namespace_cutting_psr4_prefix()
{
$this->beConstructedWith('p\pf\C\N', 'spec', dirname(__DIR__), __DIR__, null, 'p\pf');
$this->getFullSpecPath()->shouldReturn(
__DIR__.DIRECTORY_SEPARATOR.'spec'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'N'.DIRECTORY_SEPARATOR
);
}
function it_generates_proper_fullSpecPath_even_from_empty_src_namespace()
{
$this->beConstructedWith('', 'spec', dirname(__DIR__), __DIR__);
$this->getFullSpecPath()->shouldReturn(
__DIR__.DIRECTORY_SEPARATOR.'spec'.DIRECTORY_SEPARATOR
);
}
function it_stores_srcNamespace_it_was_constructed_with()
{
$this->beConstructedWith('Some\Namespace', 'spec', dirname(__DIR__), __DIR__);
$this->getSrcNamespace()->shouldReturn('Some\Namespace\\');
}
function it_trims_srcNamespace_during_construction()
{
$this->beConstructedWith('\\Some\Namespace\\', 'spec', dirname(__DIR__), __DIR__);
$this->getSrcNamespace()->shouldReturn('Some\Namespace\\');
}
function it_supports_empty_namespace_argument()
{
$this->beConstructedWith('', 'spec', dirname(__DIR__), __DIR__);
$this->getSrcNamespace()->shouldReturn('');
}
function it_generates_specNamespace_using_srcNamespace_and_specPrefix()
{
$this->beConstructedWith('Some\Namespace', 'spec', dirname(__DIR__), __DIR__);
$this->getSpecNamespace()->shouldReturn('spec\Some\Namespace\\');
}
function it_trims_specNamespace_during_construction()
{
$this->beConstructedWith('\\Some\Namespace\\', '\\spec\\ns\\', dirname(__DIR__), __DIR__);
$this->getSpecNamespace()->shouldReturn('spec\ns\Some\Namespace\\');
}
function it_generates_proper_specNamespace_for_empty_srcNamespace()
{
$this->beConstructedWith('', 'spec', dirname(__DIR__), __DIR__);
$this->getSpecNamespace()->shouldReturn('spec\\');
}
function it_finds_all_resources_from_tracked_specPath(Filesystem $fs, SplFileInfo $file)
{
$this->beConstructedWith('', 'spec', dirname(__DIR__), __DIR__, $fs);
$path = __DIR__.DIRECTORY_SEPARATOR.'spec'.DIRECTORY_SEPARATOR;
$filePath = __DIR__.$this->convert_to_path('/spec/Some/ClassSpec.php');
$fs->pathExists($path)->willReturn(true);
$fs->findSpecFilesIn($path)->willReturn(array($file));
$fs->getFileContents($filePath)->willReturn('<?php namespace spec\\Some; class ClassSpec {} ?>');
$file->getRealPath()->willReturn($filePath);
$resources = $this->getAllResources();
$resources->shouldHaveCount(1);
$resources[0]->getSpecClassname()->shouldReturn('spec\Some\ClassSpec');
}
function it_returns_empty_array_if_tracked_specPath_does_not_exist(Filesystem $fs)
{
$this->beConstructedWith('', 'spec', dirname(__DIR__), __DIR__, $fs);
$path = __DIR__.DIRECTORY_SEPARATOR.'spec'.DIRECTORY_SEPARATOR;
$fs->pathExists($path)->willReturn(false);
$resources = $this->getAllResources();
$resources->shouldHaveCount(0);
}
function it_supports_folder_queries_in_srcPath()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$this->supportsQuery($this->srcPath.'/PhpSpec')->shouldReturn(true);
}
function it_supports_srcPath_queries()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$this->supportsQuery($this->srcPath)->shouldReturn(true);
}
function it_supports_file_queries_in_srcPath()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$this->supportsQuery(
realpath($this->srcPath.'/PhpSpec/ServiceContainer.php')
)->shouldReturn(true);
}
function it_supports_folder_queries_in_specPath()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$this->supportsQuery($this->specPath.'/spec/PhpSpec')->shouldReturn(true);
}
function it_supports_specPath_queries()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$this->supportsQuery($this->specPath.'/spec')->shouldReturn(true);
}
function it_supports_file_queries_in_specPath()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$this->supportsQuery(
realpath($this->specPath.'/spec/PhpSpec/ServiceContainerSpec.php')
)->shouldReturn(true);
}
function it_does_not_support_any_other_queries()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$this->supportsQuery('/')->shouldReturn(false);
}
function it_finds_spec_resources_via_srcPath(Filesystem $fs, SplFileInfo $file)
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath, $fs);
$filePath = $this->specPath.$this->convert_to_path('/spec/PhpSpec/ContainerSpec.php');
$fs->pathExists($this->specPath.$this->convert_to_path('/spec/PhpSpec/'))->willReturn(true);
$fs->findSpecFilesIn($this->specPath.$this->convert_to_path('/spec/PhpSpec/'))->willReturn(array($file));
$fs->getFileContents($filePath)->willReturn('<?php namespace spec\\PhpSpec; class Container {} ?>');
$file->getRealPath()->willReturn($filePath);
$resources = $this->findResources($this->srcPath);
$resources->shouldHaveCount(1);
$resources[0]->getSrcClassname()->shouldReturn('PhpSpec\Container');
}
function it_finds_spec_resources_with_classname_underscores_via_srcPath(Filesystem $fs, SplFileInfo $file)
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath, $fs);
$filePath = $this->specPath.$this->convert_to_path('/spec/PhpSpec/Some/ClassSpec.php');
$fs->pathExists($this->specPath.$this->convert_to_path('/spec/PhpSpec/'))->willReturn(true);
$fs->findSpecFilesIn($this->specPath.$this->convert_to_path('/spec/PhpSpec/'))->willReturn(array($file));
$fs->getFileContents($filePath)->willReturn('<?php namespace spec\\PhpSpec; class Some_Class {} ?>');
$file->getRealPath()->willReturn($filePath);
$resources = $this->findResources($this->srcPath);
$resources->shouldHaveCount(1);
$resources[0]->getSrcClassname()->shouldReturn('PhpSpec\Some_Class');
}
function it_finds_spec_resources_via_fullSrcPath(Filesystem $fs, SplFileInfo $file)
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath, $fs);
$filePath = $this->specPath.$this->convert_to_path('/spec/PhpSpec/Console/AppSpec.php');
$fs->pathExists($this->specPath.$this->convert_to_path('/spec/PhpSpec/Console/'))->willReturn(true);
$fs->findSpecFilesIn($this->specPath.$this->convert_to_path('/spec/PhpSpec/Console/'))->willReturn(array($file));
$fs->getFileContents($filePath)->willReturn('<?php namespace spec\\PhpSpec\\Console; class App {} ?>');
$file->getRealPath()->willReturn($filePath);
$resources = $this->findResources($this->srcPath.$this->convert_to_path('/PhpSpec/Console'));
$resources->shouldHaveCount(1);
$resources[0]->getSrcClassname()->shouldReturn('PhpSpec\Console\App');
}
function it_finds_spec_resources_via_specPath(Filesystem $fs, SplFileInfo $file)
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath, $fs);
$filePath = $this->specPath.$this->convert_to_path('/spec/PhpSpec/Runner/ExampleRunnerSpec.php');
$fs->pathExists($this->specPath.$this->convert_to_path('/spec/PhpSpec/Runner/'))->willReturn(true);
$fs->findSpecFilesIn($this->specPath.$this->convert_to_path('/spec/PhpSpec/Runner/'))->willReturn(array($file));
$fs->getFileContents($filePath)->willReturn('<?php namespace spec\\PhpSpec\\Runner; class ExampleRunner {} ?>');
$file->getRealPath()->willReturn($filePath);
$resources = $this->findResources($this->specPath.$this->convert_to_path('/spec/PhpSpec/Runner'));
$resources->shouldHaveCount(1);
$resources[0]->getSrcClassname()->shouldReturn('PhpSpec\Runner\ExampleRunner');
}
function it_finds_single_spec_via_srcPath(Filesystem $fs, SplFileInfo $file)
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath, $fs);
$filePath = $this->specPath.$this->convert_to_path('/spec/PhpSpec/ServiceContainerSpec.php');
$fs->pathExists($this->specPath.$this->convert_to_path('/spec/PhpSpec/ServiceContainerSpec.php'))->willReturn(true);
$fs->getFileContents($filePath)->willReturn('<?php namespace spec\\PhpSpec; class ServiceContainer {} ?>');
$file->getRealPath()->willReturn($filePath);
$resources = $this->findResources($this->srcPath.$this->convert_to_path('/PhpSpec/ServiceContainer.php'));
$resources->shouldHaveCount(1);
$resources[0]->getSrcClassname()->shouldReturn('PhpSpec\ServiceContainer');
}
function it_finds_single_spec_via_specPath(Filesystem $fs, SplFileInfo $file)
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath, $fs);
$filePath = $this->specPath.$this->convert_to_path('/spec/PhpSpec/ServiceContainerSpec.php');
$fs->pathExists($this->specPath.$this->convert_to_path('/spec/PhpSpec/ServiceContainerSpec.php'))->willReturn(true);
$fs->getFileContents($filePath)->willReturn('<?php namespace spec\\PhpSpec; class ServiceContainer {} ?>');
$file->getRealPath()->willReturn($filePath);
$resources = $this->findResources($filePath);
$resources->shouldHaveCount(1);
$resources[0]->getSrcClassname()->shouldReturn('PhpSpec\ServiceContainer');
}
function it_returns_empty_array_if_nothing_found(Filesystem $fs)
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath, $fs);
$fs->pathExists($this->specPath.'/spec/PhpSpec/App/')->willReturn(false);
$resources = $this->findResources($this->srcPath.'/PhpSpec/App');
$resources->shouldHaveCount(0);
}
function it_throws_an_exception_on_no_class_definition(Filesystem $fs, SplFileInfo $file)
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath, $fs);
$filePath = $this->specPath.$this->convert_to_path('/spec/PhpSpec/Some/ClassSpec.php');
$fs->pathExists($this->specPath.$this->convert_to_path('/spec/PhpSpec/'))->willReturn(true);
$fs->findSpecFilesIn($this->specPath.$this->convert_to_path('/spec/PhpSpec/'))->willReturn(array($file));
$fs->getFileContents($filePath)->willReturn('no class definition');
$file->getRealPath()->willReturn($filePath);
$exception = new \RuntimeException('Spec file does not contains any class definition.');
$this->shouldThrow($exception)->duringFindResources($this->srcPath);
}
function it_does_not_throw_an_exception_on_no_class_definition_if_file_not_suffixed_with_spec(Filesystem $fs, SplFileInfo $file)
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath, $fs);
$filePath = $this->specPath.$this->convert_to_path('/spec/PhpSpec/Some/Class.php');
$fs->pathExists($this->specPath.$this->convert_to_path('/spec/PhpSpec/'))->willReturn(true);
$fs->findSpecFilesIn($this->specPath.$this->convert_to_path('/spec/PhpSpec/'))->willReturn(array());
$fs->getFileContents($filePath)->willReturn('no class definition');
$file->getRealPath()->willReturn($filePath);
$exception = new \RuntimeException('Spec file does not contains any class definition.');
$this->shouldNotThrow($exception)->duringFindResources($this->srcPath);
}
function it_throws_an_exception_when_spec_class_not_in_the_base_specs_namespace(Filesystem $fs, SplFileInfo $file)
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath, $fs);
$filePath = $this->specPath.$this->convert_to_path('/spec/PhpSpec/Some/ClassSpec.php');
$fs->pathExists($this->specPath.$this->convert_to_path('/spec/PhpSpec/'))->willReturn(true);
$fs->findSpecFilesIn($this->specPath.$this->convert_to_path('/spec/PhpSpec/'))->willReturn(array($file));
$fs->getFileContents($filePath)->willReturn('<?php namespace InvalidSpecNamespace\\PhpSpec; class ServiceContainer {} ?>');
$file->getRealPath()->willReturn($filePath);
$exception = new \RuntimeException('Spec class `InvalidSpecNamespace\\PhpSpec\\ServiceContainer` must be in the base spec namespace `spec\\PhpSpec\\`.');
$this->shouldThrow($exception)->duringFindResources($this->srcPath);
}
function it_supports_classes_from_srcNamespace()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$this->supportsClass('PhpSpec\ServiceContainer')->shouldReturn(true);
}
function it_supports_backslashed_classes_from_srcNamespace()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$this->supportsClass('PhpSpec/ServiceContainer')->shouldReturn(true);
}
function it_supports_classes_from_specNamespace()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$this->supportsClass('spec\PhpSpec\ServiceContainer')->shouldReturn(true);
}
function it_supports_backslashed_classes_from_specNamespace()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$this->supportsClass('spec/PhpSpec/ServiceContainer')->shouldReturn(true);
}
function it_supports_any_class_if_srcNamespace_is_empty()
{
$this->beConstructedWith('', 'spec', $this->srcPath, $this->specPath);
$this->supportsClass('ServiceContainer')->shouldReturn(true);
}
function it_does_not_support_anything_else()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$this->supportsClass('Acme\Any')->shouldReturn(false);
}
function it_creates_resource_from_src_class()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$resource = $this->createResource('PhpSpec\Console\Application');
$resource->getSrcClassname()->shouldReturn('PhpSpec\Console\Application');
$resource->getSpecClassname()->shouldReturn('spec\PhpSpec\Console\ApplicationSpec');
}
function it_creates_resource_from_backslashed_src_class()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$resource = $this->createResource('PhpSpec/Console/Application');
$resource->getSrcClassname()->shouldReturn('PhpSpec\Console\Application');
$resource->getSpecClassname()->shouldReturn('spec\PhpSpec\Console\ApplicationSpec');
}
function it_creates_resource_from_spec_class()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$resource = $this->createResource('spec\PhpSpec\Console\Application');
$resource->getSrcClassname()->shouldReturn('PhpSpec\Console\Application');
$resource->getSpecClassname()->shouldReturn('spec\PhpSpec\Console\ApplicationSpec');
}
function it_creates_resource_from_backslashed_spec_class()
{
$this->beConstructedWith('PhpSpec', 'spec', $this->srcPath, $this->specPath);
$resource = $this->createResource('spec/PhpSpec/Console/Application');
$resource->getSrcClassname()->shouldReturn('PhpSpec\Console\Application');
$resource->getSpecClassname()->shouldReturn('spec\PhpSpec\Console\ApplicationSpec');
}
function it_creates_resource_from_src_class_even_if_srcNamespace_is_empty()
{
$this->beConstructedWith('', 'spec', $this->srcPath, $this->specPath);
$resource = $this->createResource('Console\Application');
$resource->getSrcClassname()->shouldReturn('Console\Application');
$resource->getSpecClassname()->shouldReturn('spec\Console\ApplicationSpec');
}
function it_throws_an_exception_on_non_PSR0_resource()
{
$this->beConstructedWith('', 'spec', $this->srcPath, $this->specPath);
$exception = new \InvalidArgumentException(
'String "Non-PSR0/Namespace" is not a valid class name.'.PHP_EOL.
'Please see reference document: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md'
);
$this->shouldThrow($exception)->duringCreateResource('Non-PSR0/Namespace');
}
function it_throws_an_exception_on_PSR0_resource_with_double_backslash()
{
$this->beConstructedWith('', 'spec', $this->srcPath, $this->specPath);
$exception = new \InvalidArgumentException(
'String "NonPSR0\\\\Namespace" is not a valid class name.'.PHP_EOL.
'Please see reference document: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md'
);
$this->shouldThrow($exception)->duringCreateResource('NonPSR0\\\\Namespace');
}
function it_throws_an_exception_on_PSR0_resource_with_slash_on_the_end()
{
$this->beConstructedWith('', 'spec', $this->srcPath, $this->specPath);
$exception = new \InvalidArgumentException(
'String "Namespace/" is not a valid class name.'.PHP_EOL.
'Please see reference document: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md'
);
$this->shouldThrow($exception)->duringCreateResource('Namespace/');
}
function it_throws_an_exception_on_PSR4_prefix_not_matching_namespace()
{
$exception = new \InvalidArgumentException(
'PSR4 prefix doesn\'t match given class namespace.'.PHP_EOL
);
$this->shouldThrow($exception)->during('__construct', array('p\pf\N\S', 'spec', $this->srcPath, $this->specPath, null, 'wrong\prefix'));
}
private function convert_to_path($path)
{
if ('/' === DIRECTORY_SEPARATOR) {
return $path;
}
return str_replace('/', DIRECTORY_SEPARATOR, $path);
}
}

View File

@@ -0,0 +1,95 @@
<?php
namespace spec\PhpSpec\Locator\PSR0;
use PhpSpec\ObjectBehavior;
use PhpSpec\Locator\PSR0\PSR0Locator as Locator;
class PSR0ResourceSpec extends ObjectBehavior
{
function let(Locator $locator)
{
$this->beConstructedWith(array('usr', 'lib', 'config'), $locator);
}
function it_uses_last_segment_as_name()
{
$this->getName()->shouldReturn('config');
}
function it_uses_last_segment_plus_Spec_suffix_as_specName()
{
$this->getSpecName()->shouldReturn('configSpec');
}
function it_is_a_resource()
{
$this->shouldBeAnInstanceOf('PhpSpec\Locator\ResourceInterface');
}
function it_generates_src_filename_from_provided_parts_using_locator($locator)
{
$locator->getFullSrcPath()->willReturn('/local/');
$this->getSrcFilename()->shouldReturn('/local/usr'.DIRECTORY_SEPARATOR.'lib'.DIRECTORY_SEPARATOR.'config.php');
}
function it_generates_src_namespace_from_provided_parts_using_locator($locator)
{
$locator->getSrcNamespace()->willReturn('Local\\');
$this->getSrcNamespace()->shouldReturn('Local\usr\lib');
}
function it_generates_proper_src_namespace_even_if_there_is_only_one_part($locator)
{
$this->beConstructedWith(array('config'), $locator);
$locator->getSrcNamespace()->willReturn('Local\\');
$this->getSrcNamespace()->shouldReturn('Local');
}
function it_generates_src_classname_from_provided_parts_using_locator($locator)
{
$locator->getSrcNamespace()->willReturn('Local\\');
$this->getSrcClassname()->shouldReturn('Local\usr\lib\config');
}
function it_generates_proper_src_classname_for_empty_locator_namespace($locator)
{
$locator->getSrcNamespace()->willReturn('');
$this->getSrcClassname()->shouldReturn('usr\lib\config');
}
function it_generates_spec_filename_from_provided_parts_using_locator($locator)
{
$locator->getFullSpecPath()->willReturn('/local/spec/');
$this->getSpecFilename()->shouldReturn('/local/spec/usr'.DIRECTORY_SEPARATOR.'lib'.DIRECTORY_SEPARATOR.'configSpec.php');
}
function it_generates_spec_namespace_from_provided_parts_using_locator($locator)
{
$locator->getSpecNamespace()->willReturn('spec\Local\\');
$this->getSpecNamespace()->shouldReturn('spec\Local\usr\lib');
}
function it_generates_proper_spec_namespace_even_if_there_is_only_one_part($locator)
{
$this->beConstructedWith(array('config'), $locator);
$locator->getSpecNamespace()->willReturn('spec\Local\\');
$this->getSpecNamespace()->shouldReturn('spec\Local');
}
function it_generates_spec_classname_from_provided_parts_using_locator($locator)
{
$locator->getSpecNamespace()->willReturn('spec\Local\\');
$this->getSpecClassname()->shouldReturn('spec\Local\usr\lib\configSpec');
}
}

View File

@@ -0,0 +1,117 @@
<?php
namespace spec\PhpSpec\Locator;
use PhpSpec\ObjectBehavior;
use PhpSpec\Locator\ResourceLocatorInterface;
use PhpSpec\Locator\ResourceInterface;
class ResourceManagerSpec extends ObjectBehavior
{
function let(ResourceLocatorInterface $locator1, ResourceLocatorInterface $locator2)
{
$locator1->getPriority()->willReturn(5);
$locator2->getPriority()->willReturn(10);
}
function it_locates_resources_using_all_registered_locators($locator1, $locator2,
ResourceInterface $resource1, ResourceInterface $resource2, ResourceInterface $resource3
) {
$this->registerLocator($locator1);
$this->registerLocator($locator2);
$locator1->supportsQuery('s:query')->willReturn(true);
$locator1->findResources('s:query')->willReturn(array($resource3, $resource2));
$locator2->supportsQuery('s:query')->willReturn(true);
$locator2->findResources('s:query')->willReturn(array($resource1));
$resource1->getSpecClassname()->willReturn('Some\Spec1');
$resource2->getSpecClassname()->willReturn('Some\Spec2');
$resource3->getSpecClassname()->willReturn('Some\Spec3');
$this->locateResources('s:query')->shouldReturn(array($resource1, $resource3, $resource2));
}
function it_locates_all_locators_resources_if_query_string_is_empty($locator1, $locator2,
ResourceInterface $resource1, ResourceInterface $resource2, ResourceInterface $resource3
) {
$this->registerLocator($locator1);
$this->registerLocator($locator2);
$locator1->getAllResources()->willReturn(array($resource3, $resource2));
$locator2->getAllResources()->willReturn(array($resource1));
$resource1->getSpecClassname()->willReturn('Some\Spec1');
$resource2->getSpecClassname()->willReturn('Some\Spec2');
$resource3->getSpecClassname()->willReturn('Some\Spec3');
$this->locateResources('')->shouldReturn(array($resource1, $resource3, $resource2));
}
function it_returns_empty_array_if_registered_locators_do_not_support_query($locator1)
{
$this->registerLocator($locator1);
$locator1->supportsQuery('s:query')->willReturn(false);
$locator1->findResources('s:query')->shouldNotBeCalled();
$this->locateResources('s:query')->shouldReturn(array());
}
function it_creates_resource_from_classname_using_locator_with_highest_priority(
$locator1, $locator2, ResourceInterface $resource1, ResourceInterface $resource2
) {
$this->registerLocator($locator1);
$this->registerLocator($locator2);
$locator1->supportsClass('Some\Class')->willReturn(true);
$locator1->createResource('Some\Class')->willReturn($resource1);
$locator2->supportsClass('Some\Class')->willReturn(true);
$locator2->createResource('Some\Class')->willReturn($resource2);
$this->createResource('Some\Class')->shouldReturn($resource2);
}
function it_throws_an_exception_if_locators_do_not_support_classname($locator1)
{
$this->registerLocator($locator1);
$locator1->supportsClass('Some\Class')->willReturn(false);
$this->shouldThrow('RuntimeException')->duringCreateResource('Some\Class');
}
function it_does_not_allow_two_resources_for_the_same_spec(
$locator1, $locator2, ResourceInterface $resource1, ResourceInterface $resource2
) {
$this->registerLocator($locator1);
$this->registerLocator($locator2);
$resource1->getSpecClassname()->willReturn('Some\Spec');
$resource2->getSpecClassname()->willReturn('Some\Spec');
$locator1->getAllResources()->willReturn(array($resource1));
$locator2->getAllResources()->willReturn(array($resource2));
$this->locateResources('')->shouldReturn(array($resource2));
}
function it_uses_the_resource_from_the_highest_priority_locator_when_duplicates_occur(
$locator1, $locator2, ResourceInterface $resource1, ResourceInterface $resource2
) {
$locator1->getPriority()->willReturn(2);
$locator2->getPriority()->willReturn(1);
$this->registerLocator($locator1);
$this->registerLocator($locator2);
$resource1->getSpecClassname()->willReturn('Some\Spec');
$resource2->getSpecClassname()->willReturn('Some\Spec');
$locator1->getAllResources()->willReturn(array($resource1));
$locator2->getAllResources()->willReturn(array($resource2));
$this->locateResources('')->shouldReturn(array($resource1));
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace spec\PhpSpec\Matcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
class ArrayContainMatcherSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$presenter->presentValue(Argument::any())->willReturn('countable');
$presenter->presentString(Argument::any())->willReturnArgument();
$this->beConstructedWith($presenter);
}
function it_is_a_matcher()
{
$this->shouldBeAnInstanceOf('PhpSpec\Matcher\MatcherInterface');
}
function it_responds_to_contain()
{
$this->supports('contain', array(), array(''))->shouldReturn(true);
}
function it_matches_array_with_specified_value()
{
$this->shouldNotThrow()->duringPositiveMatch('contain', array('abc'), array('abc'));
}
function it_does_not_match_array_without_specified_value()
{
$this->shouldThrow()->duringPositiveMatch('contain', array(1,2,3), array('abc'));
$this->shouldThrow('PhpSpec\Exception\Example\FailureException')
->duringPositiveMatch('contain', array(1,2,3), array(new \stdClass()));
}
function it_matches_array_without_specified_value()
{
$this->shouldNotThrow()->duringNegativeMatch('contain', array(1,2,3), array('abc'));
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace spec\PhpSpec\Matcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use PhpSpec\Exception\Example\FailureException;
use ArrayObject;
class ArrayCountMatcherSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$presenter->presentValue(Argument::any())->willReturn('countable');
$presenter->presentString(Argument::any())->willReturnArgument();
$this->beConstructedWith($presenter);
}
function it_is_a_matcher()
{
$this->shouldBeAnInstanceOf('PhpSpec\Matcher\MatcherInterface');
}
function it_responds_to_haveCount()
{
$this->supports('haveCount', array(), array(''))->shouldReturn(true);
}
function it_matches_proper_array_count()
{
$this->shouldNotThrow()->duringPositiveMatch('haveCount', array(1,2,3), array(3));
}
function it_matches_proper_countable_count(ArrayObject $countable)
{
$countable->count()->willReturn(4);
$this->shouldNotThrow()->duringPositiveMatch('haveCount', $countable, array(4));
}
function it_does_not_match_wrong_array_count()
{
$this->shouldThrow(new FailureException('Expected countable to have 2 items, but got 3.'))
->duringPositiveMatch('haveCount', array(1,2,3), array(2));
}
function it_does_not_match_proper_countable_count(ArrayObject $countable)
{
$countable->count()->willReturn(5);
$this->shouldThrow(new FailureException('Expected countable to have 4 items, but got 5.'))
->duringPositiveMatch('haveCount', $countable, array(4));
}
function it_mismatches_wrong_array_count()
{
$this->shouldNotThrow()->duringNegativeMatch('haveCount', array(1,2,3), array(2));
}
function it_mismatches_wrong_countable_count(ArrayObject $countable)
{
$countable->count()->willReturn(5);
$this->shouldNotThrow()->duringNegativeMatch('haveCount', $countable, array(4));
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace spec\PhpSpec\Matcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use ArrayObject;
class ArrayKeyMatcherSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$presenter->presentValue(Argument::any())->willReturn('countable');
$presenter->presentString(Argument::any())->willReturnArgument();
$this->beConstructedWith($presenter);
}
function it_is_a_matcher()
{
$this->shouldBeAnInstanceOf('PhpSpec\Matcher\MatcherInterface');
}
function it_responds_to_haveKey()
{
$this->supports('haveKey', array(), array(''))->shouldReturn(true);
}
function it_matches_array_with_specified_key()
{
$this->shouldNotThrow()->duringPositiveMatch('haveKey', array('abc' => 123), array('abc'));
}
function it_matches_array_with_specified_key_even_if_there_is_no_value()
{
$this->shouldNotThrow()->duringPositiveMatch('haveKey', array('abc' => null), array('abc'));
}
function it_matches_ArrayObject_with_provided_offset(ArrayObject $array)
{
$array->offsetExists('abc')->willReturn(true);
$this->shouldNotThrow()->duringPositiveMatch('haveKey', $array, array('abc'));
}
function it_does_not_match_array_without_specified_key()
{
$this->shouldThrow()->duringPositiveMatch('haveKey', array(1,2,3), array('abc'));
}
function it_does_not_match_ArrayObject_without_provided_offset(ArrayObject $array)
{
$array->offsetExists('abc')->willReturn(false);
$this->shouldThrow()->duringPositiveMatch('haveKey', $array, array('abc'));
}
function it_matches_array_without_specified_key()
{
$this->shouldNotThrow()->duringNegativeMatch('haveKey', array(1,2,3), array('abc'));
}
function it_matches_ArrayObject_without_specified_offset(ArrayObject $array)
{
$array->offsetExists('abc')->willReturn(false);
$this->shouldNotThrow()->duringNegativeMatch('haveKey', $array, array('abc'));
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace spec\PhpSpec\Matcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use ArrayObject;
class ArrayKeyValueMatcherSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$presenter->presentValue(Argument::any())->willReturn('countable');
$presenter->presentString(Argument::any())->willReturnArgument();
$this->beConstructedWith($presenter);
}
function it_is_a_matcher()
{
$this->shouldBeAnInstanceOf('PhpSpec\Matcher\MatcherInterface');
}
function it_responds_to_haveKeyWithValue()
{
$this->supports('haveKeyWithValue', array(), array('', ''))->shouldReturn(true);
}
function it_matches_array_with_correct_value_for_specified_key()
{
$this->shouldNotThrow()->duringPositiveMatch('haveKeyWithValue', array('abc' => 123), array('abc', 123));
}
function it_matches_ArrayObject_with_correct_value_for_specified_offset(ArrayObject $array)
{
$array->offsetExists('abc')->willReturn(true);
$array->offsetGet('abc')->willReturn(123);
$this->shouldNotThrow()->duringPositiveMatch('haveKeyWithValue', $array, array('abc', 123));
}
function it_does_not_match_array_without_specified_key()
{
$this->shouldThrow()->duringPositiveMatch('haveKeyWithValue', array(1,2,3), array('abc', 123));
}
function it_does_not_match_ArrayObject_without_specified_offset(ArrayObject $array)
{
$array->offsetExists('abc')->willReturn(false);
$this->shouldThrow()->duringPositiveMatch('haveKeyWithValue', $array, array('abc', 123));
}
function it_matches_array_without_specified_key()
{
$this->shouldNotThrow()->duringNegativeMatch('haveKeyWithValue', array(1,2,3), array('abc', 123));
}
function it_matches_ArrayObject_without_specified_offset(ArrayObject $array)
{
$array->offsetExists('abc')->willReturn(false);
$this->shouldNotThrow()->duringNegativeMatch('haveKeyWithValue', $array, array('abc', 123));
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace spec\PhpSpec\Matcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
class CallbackMatcherSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$presenter->presentValue(Argument::any())->willReturn('val');
$presenter->presentString(Argument::any())->willReturnArgument();
$this->beConstructedWith('custom', function () {}, $presenter);
}
function it_is_a_matcher()
{
$this->shouldBeAnInstanceOf('PhpSpec\Matcher\MatcherInterface');
}
function it_supports_same_alias_it_was_constructed_with()
{
$this->supports('custom', array(), array())->shouldReturn(true);
}
function it_does_not_support_anything_else()
{
$this->supports('anything_else', array(), array())->shouldReturn(false);
}
function it_matches_if_callback_returns_true($presenter)
{
$this->beConstructedWith('custom', function () { return true; }, $presenter);
$this->shouldNotThrow()->duringPositiveMatch('custom', array(), array());
}
function it_does_not_match_if_callback_returns_false($presenter)
{
$this->beConstructedWith('custom', function () { return false; }, $presenter);
$this->shouldThrow()->duringPositiveMatch('custom', array(), array());
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace spec\PhpSpec\Matcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use PhpSpec\Exception\Example\FailureException;
class ComparisonMatcherSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$presenter->presentValue(Argument::any())->willReturn('val1', 'val2');
$this->beConstructedWith($presenter);
}
function it_is_a_matcher()
{
$this->shouldBeAnInstanceOf('PhpSpec\Matcher\MatcherInterface');
}
function it_responds_to_beLike()
{
$this->supports('beLike', '', array(''))->shouldReturn(true);
}
function it_matches_empty_string_using_comparison_operator()
{
$this->shouldNotThrow()->duringPositiveMatch('beLike', '', array(''));
}
function it_matches_not_empty_string_using_comparison_operator()
{
$this->shouldNotThrow()->duringPositiveMatch('beLike', 'chuck', array('chuck'));
}
function it_matches_empty_string_with_emptish_values_using_comparison_operator()
{
$this->shouldNotThrow()->duringPositiveMatch('beLike', '', array(0));
}
function it_matches_zero_with_emptish_values_using_comparison_operator()
{
$this->shouldNotThrow()->duringPositiveMatch('beLike', 0, array(''));
}
function it_matches_null_with_emptish_values_using_comparison_operator()
{
$this->shouldNotThrow()->duringPositiveMatch('beLike', null, array(''));
}
function it_matches_false_with_emptish_values_using_comparison_operator()
{
$this->shouldNotThrow()->duringPositiveMatch('beLike', false, array(''));
}
function it_does_not_match_non_empty_different_value()
{
$this->shouldThrow(new FailureException('Expected val1, but got val2.'))
->duringPositiveMatch('beLike', 'one_value', array('different_value'));
}
function it_mismatches_empty_string_using_comparison_operator()
{
$this->shouldThrow(new FailureException('Did not expect val1, but got one.'))
->duringNegativeMatch('beLike', '', array(''));
}
function it_mismatches_not_empty_string_using_comparison_operator($matcher)
{
$this->shouldThrow(new FailureException('Did not expect val1, but got one.'))
->duringNegativeMatch('beLike', 'chuck', array('chuck'));
}
function it_mismatches_empty_string_with_emptish_values_using_comparison_operator()
{
$this->shouldThrow(new FailureException('Did not expect val1, but got one.'))
->duringNegativeMatch('beLike', '', array(''));
}
function it_mismatches_zero_with_emptish_values_using_comparison_operator()
{
$this->shouldThrow(new FailureException('Did not expect val1, but got one.'))
->duringNegativeMatch('beLike', 0, array(''));
}
function it_mismatches_null_with_emptish_values_using_comparison_operator()
{
$this->shouldThrow(new FailureException('Did not expect val1, but got one.'))
->duringNegativeMatch('beLike', null, array(''));
}
function it_mismatches_false_with_emptish_values_using_comparison_operator()
{
$this->shouldThrow(new FailureException('Did not expect val1, but got one.'))
->duringNegativeMatch('beLike', false, array(''));
}
function it_mismatches_on_non_empty_different_value()
{
$this->shouldNotThrow()->duringNegativeMatch('beLike', 'one_value', array('another'));
}
}

View File

@@ -0,0 +1,121 @@
<?php
namespace spec\PhpSpec\Matcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use PhpSpec\Exception\Example\FailureException;
class IdentityMatcherSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$presenter->presentValue(Argument::any())->willReturn('val1', 'val2');
$this->beConstructedWith($presenter);
}
function it_is_a_matcher()
{
$this->shouldBeAnInstanceOf('PhpSpec\Matcher\MatcherInterface');
}
function it_responds_to_return()
{
$this->supports('return', '', array(''))->shouldReturn(true);
}
function it_responds_to_be()
{
$this->supports('be', '', array(''))->shouldReturn(true);
}
function it_responds_to_equal()
{
$this->supports('equal', '', array(''))->shouldReturn(true);
}
function it_responds_to_beEqualTo()
{
$this->supports('beEqualTo', '', array(''))->shouldReturn(true);
}
function it_matches_empty_strings()
{
$this->shouldNotThrow()->duringPositiveMatch('be', '', array(''));
}
function it_matches_not_empty_strings()
{
$this->shouldNotThrow()->duringPositiveMatch('be', 'chuck', array('chuck'));
}
function it_does_not_match_empty_string_with_emptish_values()
{
$this->shouldThrow(new FailureException('Expected val1, but got val2.'))
->duringPositiveMatch('be', '', array(false));
}
function it_does_not_match_zero_with_emptish_values()
{
$this->shouldThrow(new FailureException('Expected val1, but got val2.'))
->duringPositiveMatch('be', 0, array(false));
}
function it_does_not_match_null_with_emptish_values()
{
$this->shouldThrow(new FailureException('Expected val1, but got val2.'))
->duringPositiveMatch('be', null, array(false));
}
function it_does_not_match_false_with_emptish_values()
{
$this->shouldThrow(new FailureException('Expected val1, but got val2.'))
->duringPositiveMatch('be', false, array(''));
}
function it_does_not_match_non_empty_different_value()
{
$this->shouldThrow(new FailureException('Expected val1, but got val2.'))
->duringPositiveMatch('be', 'one', array('two'));
}
function it_mismatches_empty_string()
{
$this->shouldThrow(new FailureException('Did not expect val1, but got one.'))
->duringNegativeMatch('be', '', array(''));
}
function it_mismatches_not_empty_string($matcher)
{
$this->shouldThrow(new FailureException('Did not expect val1, but got one.'))
->duringNegativeMatch('be', 'chuck', array('chuck'));
}
function it_mismatches_empty_string_with_emptish_values()
{
$this->shouldNotThrow()->duringNegativeMatch('be', '', array(false));
}
function it_mismatches_zero_with_emptish_values_using_identity_operator()
{
$this->shouldNotThrow()->duringNegativeMatch('be', 0, array(false));
}
function it_mismatches_null_with_emptish_values_using_identity_operator()
{
$this->shouldNotThrow()->duringNegativeMatch('be', null, array(false));
}
function it_mismatches_false_with_emptish_values_using_identity_operator()
{
$this->shouldNotThrow()->duringNegativeMatch('be', false, array(''));
}
function it_mismatches_on_non_empty_different_value()
{
$this->shouldNotThrow()->duringNegativeMatch('be', 'one', array('two'));
}
}

View File

@@ -0,0 +1,93 @@
<?php
namespace spec\PhpSpec\Matcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
class ObjectStateMatcherSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$presenter->presentValue(Argument::any())->willReturn('val1', 'val2');
$presenter->presentString(Argument::any())->willReturnArgument();
$this->beConstructedWith($presenter);
}
function it_is_a_matcher()
{
$this->shouldBeAnInstanceOf('PhpSpec\Matcher\MatcherInterface');
}
function it_infers_matcher_alias_name_from_methods_prefixed_with_is()
{
$subject = new \ReflectionClass($this);
$this->supports('beAbstract', $subject, array())->shouldReturn(true);
}
function it_throws_exception_if_checker_method_not_found()
{
$subject = new \ReflectionClass($this);
$this->shouldThrow('PhpSpec\Exception\Fracture\MethodNotFoundException')
->duringPositiveMatch('beSimple', $subject, array());
}
function it_matches_if_state_checker_returns_true()
{
$subject = new \ReflectionClass($this);
$this->shouldNotThrow()->duringPositiveMatch('beUserDefined', $subject, array());
}
function it_does_not_match_if_state_checker_returns_false()
{
$subject = new \ReflectionClass($this);
$this->shouldThrow('PhpSpec\Exception\Example\FailureException')
->duringPositiveMatch('beFinal', $subject, array());
}
function it_infers_matcher_alias_name_from_methods_prefixed_with_has()
{
$subject = new \ReflectionClass($this);
$this->supports('haveProperty', $subject, array('something'))->shouldReturn(true);
}
function it_throws_exception_if_has_checker_method_not_found()
{
$subject = new \ReflectionClass($this);
$this->shouldThrow('PhpSpec\Exception\Fracture\MethodNotFoundException')
->duringPositiveMatch('haveAnything', $subject, array('str'));
}
function it_matches_if_has_checker_returns_true()
{
$subject = new \ReflectionClass($this);
$this->shouldNotThrow()->duringPositiveMatch(
'haveMethod', $subject, array('it_matches_if_has_checker_returns_true')
);
}
function it_does_not_match_if_has_state_checker_returns_false()
{
$subject = new \ReflectionClass($this);
$this->shouldThrow('PhpSpec\Exception\Example\FailureException')
->duringPositiveMatch('haveProperty', $subject, array('other'));
}
function it_does_not_match_if_subject_is_callable()
{
$subject = function () {};
$this->supports('beCallable', $subject, array())->shouldReturn(false);
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace spec\PhpSpec\Matcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
class StringEndMatcherSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$presenter->presentString(Argument::type('string'))->willReturnArgument();
$this->beConstructedWith($presenter);
}
function it_is_a_matcher()
{
$this->shouldBeAnInstanceOf('PhpSpec\Matcher\MatcherInterface');
}
function it_supports_endWith_keyword_and_string_subject()
{
$this->supports('endWith', 'hello, everzet', array('everzet'))->shouldReturn(true);
}
function it_does_not_support_anything_else()
{
$this->supports('endWith', array(), array())->shouldReturn(false);
}
function it_matches_strings_that_start_with_specified_prefix()
{
$this->shouldNotThrow()->duringPositiveMatch('endWith', 'everzet', array('zet'));
}
function it_does_not_match_strings_that_do_not_start_with_specified_prefix()
{
$this->shouldThrow()->duringPositiveMatch('endWith', 'everzet', array('tez'));
}
function it_matches_strings_that_do_not_start_with_specified_prefix()
{
$this->shouldNotThrow()->duringNegativeMatch('endWith', 'everzet', array('tez'));
}
function it_does_not_match_strings_that_do_start_with_specified_prefix()
{
$this->shouldThrow()->duringNegativeMatch('endWith', 'everzet', array('zet'));
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace spec\PhpSpec\Matcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
class StringRegexMatcherSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$presenter->presentString(Argument::type('string'))->willReturnArgument();
$this->beConstructedWith($presenter);
}
function it_is_a_matcher()
{
$this->shouldBeAnInstanceOf('PhpSpec\Matcher\MatcherInterface');
}
function it_supports_match_keyword_and_string_subject()
{
$this->supports('match', 'hello, everzet', array('/hello/'))->shouldReturn(true);
}
function it_does_not_support_anything_else()
{
$this->supports('match', array(), array())->shouldReturn(false);
}
function it_matches_strings_that_match_specified_regex()
{
$this->shouldNotThrow()->duringPositiveMatch('match', 'everzet', array('/ev.*et/'));
}
function it_does_not_match_strings_that_do_not_match_specified_regex()
{
$this->shouldThrow()->duringPositiveMatch('match', 'everzet', array('/md/'));
}
function it_matches_strings_that_do_not_match_specified_regex()
{
$this->shouldNotThrow()->duringNegativeMatch('match', 'everzet', array('/md/'));
}
function it_does_not_match_strings_that_do_match_specified_regex()
{
$this->shouldThrow()->duringNegativeMatch('match', 'everzet', array('/^ev.*et$/'));
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace spec\PhpSpec\Matcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
class StringStartMatcherSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$presenter->presentString(Argument::type('string'))->willReturnArgument();
$this->beConstructedWith($presenter);
}
function it_is_a_matcher()
{
$this->shouldBeAnInstanceOf('PhpSpec\Matcher\MatcherInterface');
}
function it_supports_startWith_keyword_and_string_subject()
{
$this->supports('startWith', 'hello, everzet', array('hello'))->shouldReturn(true);
}
function it_does_not_support_anything_else()
{
$this->supports('startWith', array(), array())->shouldReturn(false);
}
function it_matches_strings_that_start_with_specified_prefix()
{
$this->shouldNotThrow()->duringPositiveMatch('startWith', 'everzet', array('ev'));
}
function it_does_not_match_strings_that_do_not_start_with_specified_prefix()
{
$this->shouldThrow()->duringPositiveMatch('startWith', 'everzet', array('av'));
}
function it_matches_strings_that_do_not_start_with_specified_prefix()
{
$this->shouldNotThrow()->duringNegativeMatch('startWith', 'everzet', array('av'));
}
function it_does_not_match_strings_that_do_start_with_specified_prefix()
{
$this->shouldThrow()->duringNegativeMatch('startWith', 'everzet', array('ev'));
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace spec\PhpSpec\Matcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Wrapper\Unwrapper;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use ArrayObject;
class ThrowMatcherSpec extends ObjectBehavior
{
function let(Unwrapper $unwrapper, PresenterInterface $presenter)
{
$unwrapper->unwrapAll(Argument::any())->willReturnArgument();
$presenter->presentValue(Argument::any())->willReturn('val1', 'val2');
$this->beConstructedWith($unwrapper, $presenter);
}
function it_supports_the_throw_alias_for_object_and_exception_name()
{
$this->supports('throw', '', array())->shouldReturn(true);
}
function it_accepts_a_method_during_which_an_exception_should_be_thrown(ArrayObject $arr)
{
$arr->ksort()->willThrow('\Exception');
$this->positiveMatch('throw', $arr, array('\Exception'))->during('ksort', array());
}
function it_accepts_a_method_during_which_an_exception_should_not_be_thrown(ArrayObject $arr)
{
$this->negativeMatch('throw', $arr, array('\Exception'))->during('ksort', array());
}
}

View File

@@ -0,0 +1,79 @@
<?php
namespace spec\PhpSpec\Matcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use PhpSpec\Exception\Example\FailureException;
use ArrayObject;
class TypeMatcherSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$presenter->presentString(Argument::any())->willReturnArgument();
$presenter->presentValue(Argument::any())->willReturn('object');
$this->beConstructedWith($presenter);
}
function it_is_a_matcher()
{
$this->shouldBeAnInstanceOf('PhpSpec\Matcher\MatcherInterface');
}
function it_responds_to_beAnInstanceOf()
{
$this->supports('beAnInstanceOf', '', array(''))->shouldReturn(true);
}
function it_responds_to_returnAnInstanceOf()
{
$this->supports('returnAnInstanceOf', '', array(''))->shouldReturn(true);
}
function it_responds_to_haveType()
{
$this->supports('haveType', '', array(''))->shouldReturn(true);
}
function it_matches_subclass_instance(ArrayObject $object)
{
$this->shouldNotThrow()
->duringPositiveMatch('haveType', $object, array('ArrayObject'));
}
function it_matches_interface_instance(ArrayObject $object)
{
$this->shouldNotThrow()
->duringPositiveMatch('haveType', $object, array('ArrayAccess'));
}
function it_does_not_match_wrong_class(ArrayObject $object)
{
$this->shouldThrow(new FailureException(
'Expected an instance of stdClass, but got object.'
))->duringPositiveMatch('haveType', $object, array('stdClass'));
}
function it_does_not_match_wrong_interface(ArrayObject $object)
{
$this->shouldThrow(new FailureException(
'Expected an instance of SessionHandlerInterface, but got object.'
))->duringPositiveMatch('haveType', $object, array('SessionHandlerInterface'));
}
function it_matches_other_class(ArrayObject $object)
{
$this->shouldNotThrow()->duringNegativeMatch('haveType', $object, array('stdClass'));
}
function it_matches_other_interface()
{
$this->shouldNotThrow()
->duringNegativeMatch('haveType', $this, array('SessionHandlerInterface'));
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace spec\PhpSpec\Process\ReRunner;
use PhpSpec\ObjectBehavior;
use PhpSpec\Process\ReRunner;
use PhpSpec\Process\ReRunner\PlatformSpecificReRunner;
use Prophecy\Argument;
class CompositeReRunnerSpec extends ObjectBehavior
{
function let(PlatformSpecificReRunner $reRunner1, PlatformSpecificReRunner $reRunner2)
{
$this->beConstructedWith(
array(
$reRunner1->getWrappedObject(),
$reRunner2->getWrappedObject()
)
);
}
function it_is_a_rerunner()
{
$this->shouldHaveType('PhpSpec\Process\ReRunner');
}
function it_invokes_the_first_supported_child_to_rerun_the_suite_even_if_later_children_are_supported(
PlatformSpecificReRunner $reRunner1, PlatformSpecificReRunner $reRunner2
) {
$reRunner1->isSupported()->willReturn(true);
$reRunner2->isSupported()->willReturn(true);
$reRunner1->reRunSuite()->shouldBeCalled();
$this->reRunSuite();
$reRunner1->reRunSuite()->shouldHaveBeenCalled();
$reRunner2->reRunSuite()->shouldNotHaveBeenCalled();
}
function it_skips_early_child_if_it_is_not_supported_and_invokes_runsuite_on_later_supported_child(
PlatformSpecificReRunner $reRunner1, PlatformSpecificReRunner $reRunner2
) {
$reRunner1->isSupported()->willReturn(false);
$reRunner2->isSupported()->willReturn(true);
$reRunner2->reRunSuite()->willReturn();
$this->reRunSuite();
$reRunner1->reRunSuite()->shouldNotHaveBeenCalled();
$reRunner2->reRunSuite()->shouldHaveBeenCalled();
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace spec\PhpSpec\Process\ReRunner;
use PhpSpec\Console\IO;
use PhpSpec\ObjectBehavior;
use PhpSpec\Process\ReRunner;
use Prophecy\Argument;
class OptionalReRunnerSpec extends ObjectBehavior
{
function let(IO $io, ReRunner $decoratedReRunner)
{
$this->beconstructedWith($decoratedReRunner, $io);
}
function it_reruns_the_suite_if_it_is_enabled_in_the_config(IO $io, ReRunner $decoratedReRunner)
{
$io->isRerunEnabled()->willReturn(true);
$this->reRunSuite();
$decoratedReRunner->reRunSuite()->shouldHaveBeenCalled();
}
function it_does_not_rerun_the_suite_if_it_is_disabled_in_the_config(IO $io, ReRunner $decoratedReRunner)
{
$io->isRerunEnabled()->willReturn(false);
$this->reRunSuite();
$decoratedReRunner->reRunSuite()->shouldNotHaveBeenCalled();
}
}

View File

@@ -0,0 +1,38 @@
<?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 spec\PhpSpec\Process\ReRunner;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Symfony\Component\Process\PhpExecutableFinder;
class PassthruRerunnerSpec extends ObjectBehavior
{
function let(PhpExecutableFinder $executableFinder)
{
$this->beConstructedWith($executableFinder);
}
function it_is_a_rerunner()
{
$this->shouldHaveType('PhpSpec\Process\ReRunner');
}
function it_is_not_supported_when_php_process_is_not_found(PhpExecutableFinder $executableFinder)
{
$executableFinder->find()->willReturn(false);
$this->isSupported()->shouldReturn(false);
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace spec\PhpSpec\Process\ReRunner;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Symfony\Component\Process\PhpExecutableFinder;
class PcntlReRunnerSpec extends ObjectBehavior
{
function let(PhpExecutableFinder $executableFinder)
{
$this->beConstructedWith($executableFinder);
}
function it_is_a_rerunner()
{
$this->shouldHaveType('PhpSpec\Process\ReRunner');
}
function it_is_not_supported_when_php_process_is_not_found(PhpExecutableFinder $executableFinder)
{
$executableFinder->find()->willReturn(false);
$this->isSupported()->shouldReturn(false);
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace spec\PhpSpec\Runner;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use ReflectionFunction;
use ReflectionParameter;
class CollaboratorManagerSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$this->beConstructedWith($presenter);
}
function it_stores_collaborators_by_name($collaborator)
{
$this->set('custom_collaborator', $collaborator);
$this->get('custom_collaborator')->shouldReturn($collaborator);
}
function it_provides_a_method_to_check_if_collaborator_exists($collaborator)
{
$this->set('custom_collaborator', $collaborator);
$this->has('custom_collaborator')->shouldReturn(true);
$this->has('nonexistent')->shouldReturn(false);
}
function it_throws_CollaboratorException_on_attempt_to_get_unexisting_collaborator()
{
$this->shouldThrow('PhpSpec\Exception\Wrapper\CollaboratorException')
->duringGet('nonexistent');
}
function it_creates_function_arguments_for_ReflectionFunction(
ReflectionFunction $function, ReflectionParameter $param1, ReflectionParameter $param2
) {
$this->set('arg1', '123');
$this->set('arg2', '456');
$this->set('arg3', '789');
$function->getParameters()->willReturn(array($param1, $param2));
$param1->getName()->willReturn('arg1');
$param2->getName()->willReturn('arg3');
$this->getArgumentsFor($function)->shouldReturn(array('123', '789'));
}
function it_creates_null_function_arguments_for_ReflectionFunction_if_no_collaborator_found(
ReflectionFunction $function, ReflectionParameter $param1, ReflectionParameter $param2
) {
$this->set('arg1', '123');
$this->set('arg2', '456');
$this->set('arg3', '789');
$function->getParameters()->willReturn(array($param1, $param2));
$param1->getName()->willReturn('arg4');
$param2->getName()->willReturn('arg3');
$this->getArgumentsFor($function)->shouldReturn(array(null, '789'));
}
}

View File

@@ -0,0 +1,134 @@
<?php
namespace spec\PhpSpec\Runner;
use PhpSpec\ObjectBehavior;
use PhpSpec\Runner\Maintainer\LetAndLetgoMaintainer;
use Prophecy\Argument;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use PhpSpec\SpecificationInterface;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use PhpSpec\Runner\Maintainer\MaintainerInterface;
use PhpSpec\Loader\Node\SpecificationNode;
use PhpSpec\Loader\Node\ExampleNode;
use PhpSpec\Event\ExampleEvent;
use ReflectionClass;
use ReflectionMethod;
class ExampleRunnerSpec extends ObjectBehavior
{
function let(EventDispatcherInterface $dispatcher, PresenterInterface $presenter, ExampleNode $example, SpecificationNode $specification, ReflectionClass $specReflection,
ReflectionMethod $exampReflection, SpecificationInterface $context)
{
$this->beConstructedWith($dispatcher, $presenter);
$example->getSpecification()->willReturn($specification);
$example->getFunctionReflection()->willReturn($exampReflection);
$specification->getClassReflection()->willReturn($specReflection);
$specReflection->newInstance()->willReturn($context);
}
function it_executes_example_in_newly_created_context(
ExampleNode $example, ReflectionMethod $exampReflection, SpecificationInterface $context
) {
$example->isPending()->willReturn(false);
$exampReflection->getParameters()->willReturn(array());
$exampReflection->invokeArgs($context, array())->shouldBeCalled();
$this->run($example);
}
function it_dispatches_ExampleEvent_with_pending_status_if_example_is_pending(
EventDispatcherInterface $dispatcher, ExampleNode $example
) {
$example->isPending()->willReturn(true);
$dispatcher->dispatch('beforeExample', Argument::any())->shouldBeCalled();
$dispatcher->dispatch('afterExample',
Argument::which('getResult', ExampleEvent::PENDING)
)->shouldBeCalled();
$this->run($example);
}
function it_dispatches_ExampleEvent_with_failed_status_if_matcher_throws_exception(
EventDispatcherInterface $dispatcher,
ExampleNode $example, ReflectionMethod $exampReflection, SpecificationInterface $context
) {
$example->isPending()->willReturn(false);
$exampReflection->getParameters()->willReturn(array());
$exampReflection->invokeArgs($context, array())
->willThrow('PhpSpec\Exception\Example\FailureException');
$dispatcher->dispatch('beforeExample', Argument::any())->shouldBeCalled();
$dispatcher->dispatch('afterExample',
Argument::which('getResult', ExampleEvent::FAILED)
)->shouldBeCalled();
$this->run($example);
}
function it_dispatches_ExampleEvent_with_failed_status_if_example_throws_exception(
EventDispatcherInterface $dispatcher,
ExampleNode $example, ReflectionMethod $exampReflection, SpecificationInterface $context
) {
$example->isPending()->willReturn(false);
$exampReflection->getParameters()->willReturn(array());
$exampReflection->invokeArgs($context, array())->willThrow('RuntimeException');
$dispatcher->dispatch('beforeExample', Argument::any())->shouldBeCalled();
$dispatcher->dispatch('afterExample',
Argument::which('getResult', ExampleEvent::BROKEN)
)->shouldBeCalled();
$this->run($example);
}
function it_runs_all_supported_maintainers_before_and_after_each_example(
ExampleNode $example, ReflectionMethod $exampReflection, MaintainerInterface $maintainer
) {
$example->isPending()->willReturn(false);
$exampReflection->getParameters()->willReturn(array());
$exampReflection->invokeArgs(Argument::cetera())->willReturn(null);
$maintainer->getPriority()->willReturn(1);
$maintainer->supports($example)->willReturn(true);
$maintainer->prepare($example, Argument::cetera())->shouldBeCalled();
$maintainer->teardown($example, Argument::cetera())->shouldBeCalled();
$this->registerMaintainer($maintainer);
$this->run($example);
}
function it_runs_let_and_letgo_maintainer_before_and_after_each_example_if_the_example_throws_an_exception(
ExampleNode $example, SpecificationNode $specification, ReflectionClass $specReflection,
ReflectionMethod $exampReflection, LetAndLetgoMaintainer $maintainer,
SpecificationInterface $context
) {
$example->isPending()->willReturn(false);
$example->getFunctionReflection()->willReturn($exampReflection);
$example->getSpecification()->willReturn($specification);
$specification->getClassReflection()->willReturn($specReflection);
$specReflection->newInstanceArgs()->willReturn($context);
$exampReflection->getParameters()->willReturn(array());
$exampReflection->invokeArgs($context, array())->willThrow('RuntimeException');
$maintainer->getPriority()->willReturn(1);
$maintainer->supports($example)->willReturn(true);
$maintainer->prepare($example, Argument::cetera())->shouldBeCalled();
$maintainer->teardown($example, Argument::cetera())->shouldBeCalled();
$this->registerMaintainer($maintainer);
$this->run($example);
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace spec\PhpSpec\Runner\Maintainer;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use PhpSpec\Loader\Node\ExampleNode;
use PhpSpec\Matcher\MatcherInterface;
use PhpSpec\ObjectBehavior;
use PhpSpec\Runner\CollaboratorManager;
use PhpSpec\Runner\MatcherManager;
use PhpSpec\SpecificationInterface;
use Prophecy\Argument;
class MatchersMaintainerSpec extends ObjectBehavior
{
function it_should_add_default_matchers_to_the_matcher_manager(
PresenterInterface $presenter, ExampleNode $example, SpecificationInterface $context,
MatcherManager $matchers, CollaboratorManager $collaborators, MatcherInterface $matcher)
{
$this->beConstructedWith($presenter, array($matcher));
$this->prepare($example, $context, $matchers, $collaborators);
$matchers->replace(array($matcher))->shouldHaveBeenCalled();
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace spec\PhpSpec\Runner;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
use PhpSpec\Matcher\MatcherInterface;
class MatcherManagerSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$this->beConstructedWith($presenter);
}
function it_searches_in_registered_matchers(MatcherInterface $matcher)
{
$matcher->getPriority()->willReturn(0);
$matcher->supports('startWith', 'hello, world', array('hello'))->willReturn(true);
$this->add($matcher);
$this->find('startWith', 'hello, world', array('hello'))->shouldReturn($matcher);
}
function it_searches_matchers_by_their_priority(
MatcherInterface $matcher1, MatcherInterface $matcher2
) {
$matcher1->getPriority()->willReturn(2);
$matcher1->supports('startWith', 'hello, world', array('hello'))->willReturn(true);
$matcher2->getPriority()->willReturn(5);
$matcher2->supports('startWith', 'hello, world', array('hello'))->willReturn(true);
$this->add($matcher1);
$this->add($matcher2);
$this->find('startWith', 'hello, world', array('hello'))->shouldReturn($matcher2);
}
function it_throws_MatcherNotFoundException_if_matcher_not_found()
{
$this->shouldThrow('PhpSpec\Exception\Wrapper\MatcherNotFoundException')
->duringFind('startWith', 'hello, world', array('hello'));
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace spec\PhpSpec\Runner;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use PhpSpec\Runner\ExampleRunner;
use PhpSpec\Loader\Node\SpecificationNode;
use PhpSpec\Loader\Node\ExampleNode;
class SpecificationRunnerSpec extends ObjectBehavior
{
function let(EventDispatcherInterface $dispatcher, ExampleRunner $exampleRunner)
{
$this->beConstructedWith($dispatcher, $exampleRunner);
}
function it_passes_each_specification_example_to_ExampleRunner(
SpecificationNode $specification, ExampleNode $ex1, ExampleNode $ex2,
ExampleRunner $exampleRunner
) {
$specification->getExamples()->willReturn(array($ex1, $ex2));
$exampleRunner->run($ex1)->shouldBeCalled();
$exampleRunner->run($ex2)->shouldBeCalled();
$this->run($specification);
}
function it_returns_examples_max_resultCode(
SpecificationNode $specification, ExampleNode $ex1, ExampleNode $ex2,
ExampleRunner $exampleRunner
) {
$specification->getExamples()->willReturn(array($ex1, $ex2));
$exampleRunner->run($ex1)->willReturn(2);
$exampleRunner->run($ex2)->willReturn(0);
$this->run($specification)->shouldReturn(2);
}
function it_returns_0_resultCode_if_no_examples_found(SpecificationNode $specification)
{
$specification->getExamples()->willReturn(array());
$this->run($specification)->shouldReturn(0);
}
function it_dispatches_SpecificationEvent_before_and_after_examples_run(
EventDispatcherInterface $dispatcher, SpecificationNode $specification
) {
$specification->getExamples()->willReturn(array());
$dispatcher->dispatch('beforeSpecification',
Argument::type('PhpSpec\Event\SpecificationEvent')
)->shouldBeCalled();
$dispatcher->dispatch('afterSpecification',
Argument::type('PhpSpec\Event\SpecificationEvent')
)->shouldBeCalled();
$this->run($specification);
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace spec\PhpSpec\Runner;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Event\ExampleEvent;
use PhpSpec\Exception\Example\StopOnFailureException;
use PhpSpec\Loader\Suite;
use PhpSpec\Loader\Node\SpecificationNode;
use PhpSpec\Runner\SpecificationRunner;
use Symfony\Component\EventDispatcher\EventDispatcher;
class SuiteRunnerSpec extends ObjectBehavior
{
function let(EventDispatcher $dispatcher, SpecificationRunner $specRunner, Suite $suite,
SpecificationNode $spec1, SpecificationNode $spec2)
{
$this->beConstructedWith($dispatcher, $specRunner);
$suite->getSpecifications()->willReturn( array($spec1, $spec2));
}
function it_runs_all_specs_in_the_suite_through_the_specrunner($suite, $specRunner, $spec1, $spec2)
{
$this->run($suite);
$specRunner->run($spec1)->shouldHaveBeenCalled();
$specRunner->run($spec2)->shouldHaveBeenCalled();
}
function it_stops_running_subsequent_specs_when_a_spec_throws_a_StopOnFailureException($suite, $specRunner, $spec1, $spec2)
{
$specRunner->run($spec1)->willThrow(new StopOnFailureException());
$this->run($suite);
$specRunner->run($spec2)->shouldNotBeenCalled();
}
function it_returns_a_successful_result_when_all_specs_in_suite_pass($suite, $specRunner, $spec1, $spec2)
{
$specRunner->run($spec1)->willReturn(ExampleEvent::PASSED);
$specRunner->run($spec2)->willReturn(ExampleEvent::PASSED);
$this->run($suite)->shouldReturn(ExampleEvent::PASSED);
}
function it_returns_a_broken_result_when_one_spec_is_broken($suite, $specRunner, $spec1, $spec2)
{
$specRunner->run($spec1)->willReturn(ExampleEvent::FAILED);
$specRunner->run($spec2)->willReturn(ExampleEvent::BROKEN);
$this->run($suite)->shouldReturn(ExampleEvent::BROKEN);
}
function it_returns_a_failed_result_when_one_spec_failed($suite, $specRunner, $spec1, $spec2)
{
$specRunner->run($spec1)->willReturn(ExampleEvent::FAILED);
$specRunner->run($spec2)->willReturn(ExampleEvent::PENDING);
$this->run($suite)->shouldReturn(ExampleEvent::FAILED);
}
function it_dispatches_events_before_and_after_the_suite($suite, $dispatcher)
{
$this->run($suite);
$dispatcher->dispatch('beforeSuite',
Argument::type('PhpSpec\Event\SuiteEvent')
)->shouldHaveBeenCalled();
$dispatcher->dispatch('afterSuite',
Argument::type('PhpSpec\Event\SuiteEvent')
)->shouldHaveBeenCalled();
}
function it_dispatches_afterSuite_event_with_result_and_time($suite, $specRunner, $dispatcher)
{
$specRunner->run(Argument::any())->will(function () {
// Wait a few microseconds to ensure that the spec passes even on fast machines
usleep(10);
return ExampleEvent::FAILED;
});
$this->run($suite);
$dispatcher->dispatch('afterSuite',
Argument::that(
function ($event) {
return ($event->getTime() > 0)
&& ($event->getResult() == ExampleEvent::FAILED);
}
)
)->shouldHaveBeenCalled();
}
}

View File

@@ -0,0 +1,84 @@
<?php
namespace spec\PhpSpec;
use PhpSpec\ObjectBehavior;
class ServiceContainerSpec extends ObjectBehavior
{
function it_stores_parameters()
{
$this->setParam('some_param', 42);
$this->getParam('some_param')->shouldReturn(42);
}
function it_returns_null_value_for_unexisting_parameter()
{
$this->getParam('unexisting')->shouldReturn(null);
}
function it_returns_custom_default_for_unexisting_parameter_if_provided()
{
$this->getParam('unexisting', 42)->shouldReturn(42);
}
function it_stores_services($service)
{
$this->set('some_service', $service);
$this->get('some_service')->shouldReturn($service);
}
function it_throws_exception_when_trying_to_get_unexisting_service()
{
$this->shouldThrow('InvalidArgumentException')->duringGet('unexisting');
}
function it_evaluates_factory_function_set_as_service()
{
$this->set('random_number', function () { return rand(); });
$number1 = $this->get('random_number');
$number2 = $this->get('random_number');
$number1->shouldBeInteger();
$number2->shouldBeInteger();
$number2->shouldNotBe($number1);
}
function it_evaluates_factory_function_only_once_for_shared_services()
{
$this->setShared('random_number', function () { return rand(); });
$number1 = $this->get('random_number');
$number2 = $this->get('random_number');
$number2->shouldBe($number1);
}
function it_provides_a_way_to_retrieve_services_by_prefix($service1, $service2, $service3)
{
$this->set('collection1.serv1', $service1);
$this->set('collection1.serv2', $service2);
$this->set('collection2.serv3', $service3);
$this->getByPrefix('collection1')->shouldReturn(array($service1, $service2));
}
function it_provides_a_way_to_remove_service_by_key($service)
{
$this->set('collection1.some_service', $service);
$this->remove('collection1.some_service');
$this->shouldThrow()->duringGet('collection1.some_service');
$this->getByPrefix('collection1')->shouldHaveCount(0);
}
function it_supports_custom_service_configurators()
{
$this->addConfigurator(function ($c) {
$c->setParam('name', 'Jim');
});
$this->configure();
$this->getParam('name')->shouldReturn('Jim');
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace spec\PhpSpec\Util;
class ExampleObjectUsingTrait
{
use ExampleTrait, AnotherExampleTrait;
}

View File

@@ -0,0 +1,18 @@
<?php
namespace spec\PhpSpec\Util;
trait ExampleTrait
{
public function emptyMethodInTrait()
{
}
}
trait AnotherExampleTrait
{
public function nonEmptyMethodInTrait()
{
return 'foo';
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace spec\PhpSpec\Util;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class InstantiatorSpec extends ObjectBehavior
{
function it_creates_an_instance()
{
$this->instantiate('spec\PhpSpec\Util\NoConstructor')
->shouldBeAnInstanceOf('spec\PhpSpec\Util\NoConstructor');
}
function it_creates_an_instance_ignoring_constructor()
{
$this->instantiate('spec\PhpSpec\Util\WithConstructor')
->shouldBeAnInstanceOf('spec\PhpSpec\Util\WithConstructor');
}
function it_creates_an_instance_with_properties()
{
$this->instantiate('spec\PhpSpec\Util\WithProperties')
->shouldBeAnInstanceOf('spec\PhpSpec\Util\WithProperties');
}
function it_complains_if_class_does_not_exist()
{
$this->shouldThrow('PhpSpec\Exception\Fracture\ClassNotFoundException')
->duringInstantiate('NonExistingClass');
}
}
class NoConstructor
{
}
class WithConstructor
{
public function __construct($requiredArgument)
{
}
}
class WithProperties
{
private $foo;
protected $bar;
public $baz;
}

View File

@@ -0,0 +1,99 @@
<?php
namespace spec\PhpSpec\Util;
use PhpSpec\Exception\Example\SkippingException;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MethodAnalyserSpec extends ObjectBehavior
{
function it_identifies_empty_methods_as_empty()
{
$this->methodIsEmpty('spec\PhpSpec\Util\ExampleObject', 'emptyMethod')->shouldReturn(true);
$this->methodIsEmpty('spec\PhpSpec\Util\ExampleObject', 'emptyMethod2')->shouldReturn(true);
}
function it_identifies_commented_methods_as_empty()
{
$this->methodIsEmpty('spec\PhpSpec\Util\ExampleObject', 'commentedMethod')->shouldReturn(true);
}
function it_identifies_methods_with_code_as_not_empty()
{
$this->methodIsEmpty('spec\PhpSpec\Util\ExampleObject', 'nonEmptyMethod')->shouldReturn(false);
}
function it_identifies_methods_without_standard_braces_as_non_empty()
{
$this->methodIsEmpty('spec\PhpSpec\Util\ExampleObject', 'nonEmptyOneLineMethod')->shouldReturn(false);
$this->methodIsEmpty('spec\PhpSpec\Util\ExampleObject', 'nonEmptyOneLineMethod2')->shouldReturn(false);
$this->methodIsEmpty('spec\PhpSpec\Util\ExampleObject', 'nonEmptyOneLineMethod3')->shouldReturn(false);
$this->methodIsEmpty('spec\PhpSpec\Util\ExampleObject', 'nonEmptyMethod2')->shouldReturn(false);
}
function it_identifies_internal_classes_as_non_empty()
{
$this->methodIsEmpty('DateTimeZone', 'getOffset')->shouldReturn(false);
}
function it_identifies_methods_from_traits()
{
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
throw new SkippingException('Traits implemented since PHP 5.4');
}
$this->methodIsEmpty('spec\PhpSpec\Util\ExampleObjectUsingTrait', 'emptyMethodInTrait')->shouldReturn(true);
$this->methodIsEmpty('spec\PhpSpec\Util\ExampleObjectUsingTrait', 'nonEmptyMethodInTrait')->shouldReturn(false);
}
function it_finds_the_real_declaring_class_of_a_method()
{
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
throw new SkippingException('Traits implemented since PHP 5.4');
}
$this->getMethodOwnerName('spec\PhpSpec\Util\ExampleObjectUsingTrait', 'emptyMethodInTrait')
->shouldReturn('spec\PhpSpec\Util\ExampleTrait');
}
}
class ExampleObject
{
public function emptyMethod() {}
public function emptyMethod2()
{}
public function commentedMethod()
{
/**
* this is a comment
*/
// This is a comment
/* this is a comment {} */
}
public function nonEmptyMethod()
{
/**
* a comment to fool us
*/
$variable = true;
// another comment
}
public function nonEmptyMethod2() { return 'foo';
}
public function nonEmptyOneLineMethod() { return 'foo'; }
public function nonEmptyOneLineMethod2()
{ return 'foo'; }
public function nonEmptyOneLineMethod3() {
return 'foo';
}
}

View File

@@ -0,0 +1,228 @@
<?php
namespace spec\PhpSpec\Wrapper\Subject;
use PhpSpec\Exception\ExceptionFactory;
use PhpSpec\Wrapper\Subject\WrappedObject;
use PhpSpec\Wrapper\Wrapper;
use PhpSpec\Wrapper\Subject;
use PhpSpec\Loader\Node\ExampleNode;
use Symfony\Component\EventDispatcher\EventDispatcherInterface as Dispatcher;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CallerSpec extends ObjectBehavior
{
function let(WrappedObject $wrappedObject, ExampleNode $example,
Dispatcher $dispatcher, ExceptionFactory $exceptions, Wrapper $wrapper)
{
$this->beConstructedWith($wrappedObject, $example, $dispatcher,
$exceptions, $wrapper);
}
function it_dispatches_method_call_events(Dispatcher $dispatcher, WrappedObject $wrappedObject)
{
$wrappedObject->isInstantiated()->willReturn(true);
$wrappedObject->getInstance()->willReturn(new \ArrayObject());
$dispatcher->dispatch(
'beforeMethodCall',
Argument::type('PhpSpec\Event\MethodCallEvent')
)->shouldBeCalled();
$dispatcher->dispatch(
'afterMethodCall',
Argument::type('PhpSpec\Event\MethodCallEvent')
)->shouldBeCalled();
$this->call('count');
}
function it_sets_a_property_on_the_wrapped_object(WrappedObject $wrappedObject)
{
$obj = new \stdClass();
$obj->id = 1;
$wrappedObject->isInstantiated()->willReturn(true);
$wrappedObject->getInstance()->willReturn($obj);
$this->set('id', 2)->shouldReturn(2);
}
function it_proxies_method_calls_to_wrapped_object(\ArrayObject $obj, WrappedObject $wrappedObject)
{
$obj->asort()->shouldBeCalled();
$wrappedObject->isInstantiated()->willReturn(true);
$wrappedObject->getInstance()->willReturn($obj);
$this->call('asort');
}
function it_delegates_throwing_class_not_found_exception(WrappedObject $wrappedObject, ExceptionFactory $exceptions)
{
$wrappedObject->isInstantiated()->willReturn(false);
$wrappedObject->getClassName()->willReturn('Foo');
$exceptions->classNotFound('Foo')
->willReturn(new \PhpSpec\Exception\Fracture\ClassNotFoundException(
'Class "Foo" does not exist.',
'"Foo"'
))
->shouldBeCalled();
$this->shouldThrow('\PhpSpec\Exception\Fracture\ClassNotFoundException')
->duringGetWrappedObject();
}
function it_delegates_throwing_method_not_found_exception(WrappedObject $wrappedObject, ExceptionFactory $exceptions)
{
$obj = new \ArrayObject();
$wrappedObject->isInstantiated()->willReturn(true);
$wrappedObject->getInstance()->willReturn($obj);
$wrappedObject->getClassName()->willReturn('ArrayObject');
$exceptions->methodNotFound('ArrayObject', 'foo', array())
->willReturn(new \PhpSpec\Exception\Fracture\MethodNotFoundException(
'Method "foo" not found.',
$obj,
'"ArrayObject::foo"',
array()
))
->shouldBeCalled();
$this->shouldThrow('\PhpSpec\Exception\Fracture\MethodNotFoundException')
->duringCall('foo');
}
function it_delegates_throwing_method_not_found_exception_for_constructor(WrappedObject $wrappedObject, ExceptionFactory $exceptions, \stdClass $argument)
{
$obj = new ExampleClass();
$wrappedObject->isInstantiated()->willReturn(false);
$wrappedObject->getInstance()->willReturn(null);
$wrappedObject->getArguments()->willReturn(array($argument));
$wrappedObject->getClassName()->willReturn('spec\PhpSpec\Wrapper\Subject\ExampleClass');
$wrappedObject->getFactoryMethod()->willReturn(null);
$exceptions->methodNotFound('spec\PhpSpec\Wrapper\Subject\ExampleClass', '__construct', array($argument))
->willReturn(new \PhpSpec\Exception\Fracture\MethodNotFoundException(
'Method "__construct" not found.',
$obj,
'"ExampleClass::__construct"',
array()
))
->shouldBeCalled();
$this->shouldThrow('\PhpSpec\Exception\Fracture\MethodNotFoundException')
->duringCall('__construct');
}
function it_delegates_throwing_named_constructor_not_found_exception(WrappedObject $wrappedObject, ExceptionFactory $exceptions)
{
$obj = new \ArrayObject();
$arguments = array('firstname', 'lastname');
$wrappedObject->isInstantiated()->willReturn(false);
$wrappedObject->getInstance()->willReturn(null);
$wrappedObject->getClassName()->willReturn('ArrayObject');
$wrappedObject->getFactoryMethod()->willReturn('register');
$wrappedObject->getArguments()->willReturn($arguments);
$exceptions->namedConstructorNotFound('ArrayObject', 'register', $arguments)
->willReturn(new \PhpSpec\Exception\Fracture\NamedConstructorNotFoundException(
'Named constructor "register" not found.',
$obj,
'"ArrayObject::register"',
array()
))
->shouldBeCalled();
$this->shouldThrow('\PhpSpec\Exception\Fracture\NamedConstructorNotFoundException')
->duringCall('foo');
}
function it_delegates_throwing_method_not_visible_exception(WrappedObject $wrappedObject, ExceptionFactory $exceptions)
{
$obj = new ExampleClass();
$wrappedObject->isInstantiated()->willReturn(true);
$wrappedObject->getInstance()->willReturn($obj);
$wrappedObject->getClassName()->willReturn('spec\PhpSpec\Wrapper\Subject\ExampleClass');
$exceptions->methodNotVisible('spec\PhpSpec\Wrapper\Subject\ExampleClass', 'privateMethod', array())
->willReturn(new \PhpSpec\Exception\Fracture\MethodNotVisibleException(
'Method "privateMethod" not visible.',
$obj,
'"ExampleClass::privateMethod"',
array()
))
->shouldBeCalled();
$this->shouldThrow('\PhpSpec\Exception\Fracture\MethodNotVisibleException')
->duringCall('privateMethod');
}
function it_delegates_throwing_property_not_found_exception(WrappedObject $wrappedObject, ExceptionFactory $exceptions)
{
$obj = new ExampleClass();
$wrappedObject->isInstantiated()->willReturn(true);
$wrappedObject->getInstance()->willReturn($obj);
$exceptions->propertyNotFound($obj, 'nonExistentProperty')
->willReturn(new \PhpSpec\Exception\Fracture\PropertyNotFoundException(
'Property "nonExistentProperty" not found.',
$obj,
'nonExistentProperty'
))
->shouldBeCalled();
$this->shouldThrow('\PhpSpec\Exception\Fracture\PropertyNotFoundException')
->duringSet('nonExistentProperty', 'any value');
}
function it_delegates_throwing_calling_method_on_non_object_exception(ExceptionFactory $exceptions)
{
$exceptions->callingMethodOnNonObject('foo')
->willReturn(new \PhpSpec\Exception\Wrapper\SubjectException(
'Call to a member function "foo()" on a non-object.'
))
->shouldBeCalled();
$this->shouldThrow('\PhpSpec\Exception\Wrapper\SubjectException')
->duringCall('foo');
}
function it_delegates_throwing_setting_property_on_non_object_exception(ExceptionFactory $exceptions)
{
$exceptions->settingPropertyOnNonObject('foo')
->willReturn(new \PhpSpec\Exception\Wrapper\SubjectException(
'Setting property "foo" on a non-object.'
))
->shouldBeCalled();
$this->shouldThrow('\PhpSpec\Exception\Wrapper\SubjectException')
->duringSet('foo');
}
function it_delegates_throwing_getting_property_on_non_object_exception(ExceptionFactory $exceptions)
{
$exceptions->gettingPropertyOnNonObject('foo')
->willReturn(new \PhpSpec\Exception\Wrapper\SubjectException(
'Getting property "foo" on a non-object.'
))
->shouldBeCalled();
$this->shouldThrow('\PhpSpec\Exception\Wrapper\SubjectException')
->duringGet('foo');
}
}
class ExampleClass
{
private function privateMethod()
{
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace spec\PhpSpec\Wrapper\Subject\Expectation;
use PhpSpec\ObjectBehavior;
use PhpSpec\Wrapper\Subject;
use PhpSpec\Wrapper\Subject\WrappedObject;
use Prophecy\Argument;
use PhpSpec\Wrapper\Subject\Expectation\ExpectationInterface;
class ConstructorDecoratorSpec extends ObjectBehavior
{
function let(ExpectationInterface $expectation)
{
$this->beConstructedWith($expectation);
}
function it_rethrows_php_errors_as_phpspec_error_exceptions(Subject $subject, WrappedObject $wrapped)
{
$subject->callOnWrappedObject('getWrappedObject', array())->willThrow('PhpSpec\Exception\Example\ErrorException');
$this->shouldThrow('PhpSpec\Exception\Example\ErrorException')->duringMatch('be', $subject, array(), $wrapped);
}
function it_rethrows_fracture_errors_as_phpspec_error_exceptions(Subject $subject, WrappedObject $wrapped)
{
$subject->__call('getWrappedObject', array())->willThrow('PhpSpec\Exception\Fracture\FractureException');
$this->shouldThrow('PhpSpec\Exception\Fracture\FractureException')->duringMatch('be', $subject, array(), $wrapped);
}
function it_ignores_any_other_exception(Subject $subject, WrappedObject $wrapped)
{
$subject->callOnWrappedObject('getWrappedObject', array())->willThrow('\Exception');
$wrapped->getClassName()->willReturn('\stdClass');
$this->shouldNotThrow('\Exception')->duringMatch('be', $subject, array(), $wrapped);
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace spec\PhpSpec\Wrapper\Subject\Expectation;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Wrapper\Subject\Expectation\Decorator as AbstractDecorator;
use PhpSpec\Wrapper\Subject\Expectation\ExpectationInterface;
class DecoratorSpec extends ObjectBehavior
{
function let(ExpectationInterface $expectation)
{
$this->beAnInstanceOf('spec\PhpSpec\Wrapper\Subject\Expectation\Decorator');
$this->beConstructedWith($expectation);
}
function it_returns_the_decorated_expectation(ExpectationInterface $expectation)
{
$this->getExpectation()->shouldReturn($expectation);
}
function it_keeps_looking_for_nested_expectations(AbstractDecorator $decorator, ExpectationInterface $expectation)
{
$decorator->getExpectation()->willReturn($expectation);
$this->beAnInstanceOf('spec\PhpSpec\Wrapper\Subject\Expectation\Decorator');
$this->beConstructedWith($decorator);
$this->getNestedExpectation()->shouldReturn($expectation);
}
}
class Decorator extends AbstractDecorator
{
public function match($alias, $subject, array $arguments = array())
{
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace spec\PhpSpec\Wrapper\Subject\Expectation;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Wrapper\Subject\Expectation\ExpectationInterface;
use PhpSpec\Loader\Node\ExampleNode;
use PhpSpec\Matcher\MatcherInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use PhpSpec\Event\ExpectationEvent;
class DispatcherDecoratorSpec extends ObjectBehavior
{
function let(ExpectationInterface $expectation, EventDispatcherInterface $dispatcher, MatcherInterface $matcher, ExampleNode $example)
{
$this->beConstructedWith($expectation, $dispatcher, $matcher, $example);
}
function it_implements_the_interface_of_the_decorated()
{
$this->shouldImplement('PhpSpec\Wrapper\Subject\Expectation\ExpectationInterface');
}
function it_dispatches_before_and_after_events(EventDispatcherInterface $dispatcher)
{
$alias = 'be';
$subject = new \stdClass();
$arguments = array();
$dispatcher->dispatch('beforeExpectation', Argument::type('PhpSpec\Event\ExpectationEvent'))->shouldBeCalled();
$dispatcher->dispatch('afterExpectation', Argument::which('getResult', ExpectationEvent::PASSED))->shouldBeCalled();
$this->match($alias, $subject, $arguments);
}
function it_decorates_expectation_with_failed_event(ExpectationInterface $expectation, EventDispatcherInterface $dispatcher)
{
$alias = 'be';
$subject = new \stdClass();
$arguments = array();
$expectation->match(Argument::cetera())->willThrow('PhpSpec\Exception\Example\FailureException');
$dispatcher->dispatch('beforeExpectation', Argument::type('PhpSpec\Event\ExpectationEvent'))->shouldBeCalled();
$dispatcher->dispatch('afterExpectation', Argument::which('getResult', ExpectationEvent::FAILED))->shouldBeCalled();
$this->shouldThrow('PhpSpec\Exception\Example\FailureException')->duringMatch($alias, $subject, $arguments);
}
function it_decorates_expectation_with_broken_event(ExpectationInterface $expectation, EventDispatcherInterface $dispatcher)
{
$alias = 'be';
$subject = new \stdClass();
$arguments = array();
$expectation->match(Argument::cetera())->willThrow('\RuntimeException');
$dispatcher->dispatch('beforeExpectation', Argument::type('PhpSpec\Event\ExpectationEvent'))->shouldBeCalled();
$dispatcher->dispatch('afterExpectation', Argument::which('getResult', ExpectationEvent::BROKEN))->shouldBeCalled();
$this->shouldThrow('\RuntimeException')->duringMatch($alias, $subject, $arguments);
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace spec\PhpSpec\Wrapper\Subject\Expectation;
use PhpSpec\ObjectBehavior;
use PhpSpec\Wrapper\Subject;
use Prophecy\Argument;
use PhpSpec\Matcher\MatcherInterface;
class NegativeSpec extends ObjectBehavior
{
function let(MatcherInterface $matcher)
{
$this->beConstructedWith($matcher);
}
function it_calls_a_negative_match_on_matcher(MatcherInterface $matcher)
{
$alias = 'somealias';
$subject = 'subject';
$arguments = array();
$matcher->negativeMatch($alias, $subject, $arguments)->shouldBeCalled();
$this->match($alias, $subject, $arguments);
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace spec\PhpSpec\Wrapper\Subject\Expectation;
use PhpSpec\Matcher\MatcherInterface;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class PositiveSpec extends ObjectBehavior
{
function let(MatcherInterface $matcher)
{
$this->beConstructedWith($matcher);
}
function it_calls_a_positive_match_on_matcher(MatcherInterface $matcher)
{
$alias = 'somealias';
$subject = 'subject';
$arguments = array();
$matcher->positiveMatch($alias, $subject, $arguments)->shouldBeCalled();
$this->match($alias, $subject, $arguments);
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace spec\PhpSpec\Wrapper\Subject;
use PhpSpec\Matcher\MatcherInterface;
use PhpSpec\ObjectBehavior;
use PhpSpec\Wrapper\Subject;
use Prophecy\Argument;
use PhpSpec\Loader\Node\ExampleNode;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use PhpSpec\Runner\MatcherManager;
class ExpectationFactorySpec extends ObjectBehavior
{
function let(ExampleNode $example, EventDispatcherInterface $dispatcher, MatcherManager $matchers)
{
$this->beConstructedWith($example, $dispatcher, $matchers);
}
function it_creates_positive_expectations(MatcherManager $matchers, MatcherInterface $matcher, Subject $subject)
{
$matchers->find(Argument::cetera())->willReturn($matcher);
$subject->__call('getWrappedObject', array())->willReturn(new \stdClass());
$decoratedExpecation = $this->create('shouldBe', $subject);
$decoratedExpecation->shouldHaveType('PhpSpec\Wrapper\Subject\Expectation\Decorator');
$decoratedExpecation->getNestedExpectation()->shouldHaveType('PhpSpec\Wrapper\Subject\Expectation\Positive');
}
function it_creates_negative_expectations(MatcherManager $matchers, MatcherInterface $matcher, Subject $subject)
{
$matchers->find(Argument::cetera())->willReturn($matcher);
$subject->__call('getWrappedObject', array())->willReturn(new \stdClass());
$decoratedExpecation = $this->create('shouldNotbe', $subject);
$decoratedExpecation->shouldHaveType('PhpSpec\Wrapper\Subject\Expectation\Decorator');
$decoratedExpecation->getNestedExpectation()->shouldHaveType('PhpSpec\Wrapper\Subject\Expectation\Negative');
}
function it_creates_positive_throw_expectations(MatcherManager $matchers, MatcherInterface $matcher, Subject $subject)
{
$matchers->find(Argument::cetera())->willReturn($matcher);
$subject->__call('getWrappedObject', array())->willReturn(new \stdClass());
$expectation = $this->create('shouldThrow', $subject);
$expectation->shouldHaveType('PhpSpec\Wrapper\Subject\Expectation\PositiveThrow');
}
function it_creates_negative_throw_expectations(MatcherManager $matchers, MatcherInterface $matcher, Subject $subject)
{
$matchers->find(Argument::cetera())->willReturn($matcher);
$subject->__call('getWrappedObject', array())->willReturn(new \stdClass());
$expectation = $this->create('shouldNotThrow', $subject);
$expectation->shouldHaveType('PhpSpec\Wrapper\Subject\Expectation\NegativeThrow');
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace spec\PhpSpec\Wrapper\Subject;
use PhpSpec\Exception\Fracture\FactoryDoesNotReturnObjectException;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Formatter\Presenter\PresenterInterface;
class WrappedObjectSpec extends ObjectBehavior
{
function let(PresenterInterface $presenter)
{
$this->beConstructedWith(null, $presenter);
}
function it_instantiates_object_using_classname()
{
$this->callOnWrappedObject('beAnInstanceOf', array('ArrayObject'));
$this->instantiate()->shouldHaveType('ArrayObject');
}
function it_keeps_instantiated_object()
{
$this->callOnWrappedObject('beAnInstanceOf', array('ArrayObject'));
$this->instantiate()->shouldBeEqualTo($this->getInstance());
}
function it_can_be_instantiated_with_a_factory_method()
{
$this->callOnWrappedObject(
'beConstructedThrough',
array(
'\DateTime::createFromFormat',
array('d-m-Y', '01-01-1970')
)
);
$this->instantiate()->shouldHaveType('\DateTime');
}
function it_can_be_instantiated_with_a_factory_method_with_method_name_only()
{
$this->callOnWrappedObject('beAnInstanceOf', array('\DateTime'));
$this->callOnWrappedObject(
'beConstructedThrough',
array(
'createFromFormat',
array('d-m-Y', '01-01-1970')
)
);
$this->instantiate()->shouldHaveType('\DateTime');
}
function it_throws_an_exception_when_factory_method_returns_a_non_object()
{
$this->callOnWrappedObject('beAnInstanceOf', array('\DateTimeZone'));
$this->callOnWrappedObject('beConstructedThrough', array('listAbbreviations'));
$message = 'The method \DateTimeZone::listAbbreviations did not return an object, returned array instead';
$this->shouldThrow(new FactoryDoesNotReturnObjectException($message))->duringInstantiate();
}
function it_throws_an_exception_when_trying_to_change_constructor_params_after_instantiation()
{
$this->callOnWrappedObject('beAnInstanceOf', array('\DateTime'));
$this->callOnWrappedObject('beConstructedWith', array(array('now')));
$this->callOnWrappedObject('instantiate', array());
$this->shouldThrow('PhpSpec\Exception\Wrapper\SubjectException')->duringBeConstructedWith('tomorrow');
}
function it_throws_an_exception_when_trying_to_change_factory_method_after_instantiation()
{
$this->callOnWrappedObject('beAnInstanceOf', array('\DateTime'));
$this->callOnWrappedObject('beConstructedThrough', array('createFromFormat',array('d-m-Y', '01-01-1980')));
$this->callOnWrappedObject('instantiate', array());
$this->shouldThrow('PhpSpec\Exception\Wrapper\SubjectException')
->duringBeConstructedThrough(array('createFromFormat',array('d-m-Y', '01-01-1970')));
}
function it_throws_an_exception_when_trying_to_change_from_constructor_to_factory_method_after_instantiation()
{
$this->callOnWrappedObject('beAnInstanceOf', array('\DateTime'));
$this->callOnWrappedObject('beConstructedWith', array(array('now')));
$this->callOnWrappedObject('instantiate', array());
$this->shouldThrow('PhpSpec\Exception\Wrapper\SubjectException')
->duringBeConstructedThrough(array('createFromFormat',array('d-m-Y', '01-01-1970')));
}
function it_throws_an_exception_when_trying_to_change_from_factory_method_to_constructor_after_instantiation()
{
$this->callOnWrappedObject('beAnInstanceOf', array('\DateTime'));
$this->callOnWrappedObject('beConstructedThrough', array('createFromFormat',array('d-m-Y', '01-01-1980')));
$this->callOnWrappedObject('instantiate', array());
$this->shouldThrow('PhpSpec\Exception\Wrapper\SubjectException')->duringBeConstructedWith('tomorrow');
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace spec\PhpSpec\Wrapper;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Wrapper\Wrapper;
use PhpSpec\Wrapper\Subject\WrappedObject;
use PhpSpec\Wrapper\Subject\Caller;
use PhpSpec\Wrapper\Subject\SubjectWithArrayAccess;
use PhpSpec\Wrapper\Subject\ExpectationFactory;
use PhpSpec\Wrapper\Subject\Expectation\ExpectationInterface;
class SubjectSpec extends ObjectBehavior
{
function let(Wrapper $wrapper, WrappedObject $wrappedObject, Caller $caller,
SubjectWithArrayAccess $arrayAccess, ExpectationFactory $expectationFactory)
{
$this->beConstructedWith(null, $wrapper, $wrappedObject, $caller, $arrayAccess, $expectationFactory);
}
function it_passes_the_created_subject_to_expectation(WrappedObject $wrappedObject,
ExpectationFactory $expectationFactory, ExpectationInterface $expectation)
{
$expectation->match(Argument::cetera())->willReturn(true);
$wrappedObject->getClassName()->willReturn('spec\PhpSpec\Wrapper\Everything');
$expectationFactory->create(Argument::cetera())->willReturn($expectation);
$this->callOnWrappedObject('shouldBeAlright');
$expectationFactory->create(Argument::any(), Argument::type('spec\PhpSpec\Wrapper\Everything'), Argument::any())->shouldHaveBeenCalled();
}
function it_passes_the_existing_subject_to_expectation(Wrapper $wrapper, WrappedObject $wrappedObject, Caller $caller,
SubjectWithArrayAccess $arrayAccess, ExpectationFactory $expectationFactory, ExpectationInterface $expectation)
{
$existingSubject = new \ArrayObject();
$this->beConstructedWith($existingSubject, $wrapper, $wrappedObject, $caller, $arrayAccess, $expectationFactory);
$expectation->match(Argument::cetera())->willReturn(true);
$wrappedObject->getClassName()->willReturn('\ArrayObject');
$expectationFactory->create(Argument::cetera())->willReturn($expectation);
$this->callOnWrappedObject('shouldBeAlright');
$expectationFactory->create(Argument::any(), Argument::exact($existingSubject), Argument::any())->shouldHaveBeenCalled();
}
}
class Everything
{
public function isAlright()
{
return true;
}
}