Revert "My first commit of codes"

This reverts commit a6e5a69348.
This commit is contained in:
sujitprasad
2015-05-01 13:27:00 +05:30
parent 6f37d10de3
commit 16ea6e1984
8487 changed files with 0 additions and 1317246 deletions

View File

@@ -1,58 +0,0 @@
PHP Diff Class
--------------
Introduction
------------
A comprehensive library for generating differences between
two hashable objects (strings or arrays). Generated differences can be
rendered in all of the standard formats including:
* Unified
* Context
* Inline HTML
* Side by Side HTML
The logic behind the core of the diff engine (ie, the sequence matcher)
is primarily based on the Python difflib package. The reason for doing
so is primarily because of its high degree of accuracy.
Example Use
-----------
A quick usage example can be found in the example/ directory and under
example.php.
More complete documentation will be available shortly.
Todo
----
* Ability to ignore blank line changes
* 3 way diff support
* Performance optimizations
License (BSD License)
---------------------
Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Chris Boulton nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,19 +0,0 @@
{
"name": "phpspec/php-diff",
"type": "library",
"description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).",
"license": "BSD-3-Clause",
"authors": [
{
"name": "Chris Boulton",
"homepage": "http://github.com/chrisboulton"
}
],
"autoload": {
"psr-0": {
"Diff": "lib/"
}
}
}

View File

@@ -1,13 +0,0 @@
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Hello World!</title>
</head>
<body>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<h2>A heading we'll be removing</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</body>
</html>

View File

@@ -1,14 +0,0 @@
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Goodbye Cruel World!</title>
</head>
<body>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Just a small amount of new text...</p>
</body>
</html>

View File

@@ -1,69 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>PHP LibDiff - Examples</title>
<link rel="stylesheet" href="styles.css" type="text/css" charset="utf-8"/>
</head>
<body>
<h1>PHP LibDiff - Examples</h1>
<hr />
<?php
// Include the diff class
require_once dirname(__FILE__).'/../lib/Diff.php';
// Include two sample files for comparison
$a = explode("\n", file_get_contents(dirname(__FILE__).'/a.txt'));
$b = explode("\n", file_get_contents(dirname(__FILE__).'/b.txt'));
// Options for generating the diff
$options = array(
//'ignoreWhitespace' => true,
//'ignoreCase' => true,
);
// Initialize the diff class
$diff = new Diff($a, $b, $options);
?>
<h2>Side by Side Diff</h2>
<?php
// Generate a side by side diff
require_once dirname(__FILE__).'/../lib/Diff/Renderer/Html/SideBySide.php';
$renderer = new Diff_Renderer_Html_SideBySide;
echo $diff->Render($renderer);
?>
<h2>Inline Diff</h2>
<?php
// Generate an inline diff
require_once dirname(__FILE__).'/../lib/Diff/Renderer/Html/Inline.php';
$renderer = new Diff_Renderer_Html_Inline;
echo $diff->render($renderer);
?>
<h2>Unified Diff</h2>
<pre><?php
// Generate a unified diff
require_once dirname(__FILE__).'/../lib/Diff/Renderer/Text/Unified.php';
$renderer = new Diff_Renderer_Text_Unified;
echo htmlspecialchars($diff->render($renderer));
?>
</pre>
<h2>Context Diff</h2>
<pre><?php
// Generate a context diff
require_once dirname(__FILE__).'/../lib/Diff/Renderer/Text/Context.php';
$renderer = new Diff_Renderer_Text_Context;
echo htmlspecialchars($diff->render($renderer));
?>
</pre>
</body>
</html>

View File

@@ -1,93 +0,0 @@
body {
background: #fff;
font-family: Arial;
font-size: 12px;
}
.Differences {
width: 100%;
border-collapse: collapse;
border-spacing: 0;
empty-cells: show;
}
.Differences thead th {
text-align: left;
border-bottom: 1px solid #000;
background: #aaa;
color: #000;
padding: 4px;
}
.Differences tbody th {
text-align: right;
background: #ccc;
width: 4em;
padding: 1px 2px;
border-right: 1px solid #000;
vertical-align: top;
font-size: 13px;
}
.Differences td {
padding: 1px 2px;
font-family: Consolas, monospace;
font-size: 13px;
}
.DifferencesSideBySide .ChangeInsert td.Left {
background: #dfd;
}
.DifferencesSideBySide .ChangeInsert td.Right {
background: #cfc;
}
.DifferencesSideBySide .ChangeDelete td.Left {
background: #f88;
}
.DifferencesSideBySide .ChangeDelete td.Right {
background: #faa;
}
.DifferencesSideBySide .ChangeReplace .Left {
background: #fe9;
}
.DifferencesSideBySide .ChangeReplace .Right {
background: #fd8;
}
.Differences ins, .Differences del {
text-decoration: none;
}
.DifferencesSideBySide .ChangeReplace ins, .DifferencesSideBySide .ChangeReplace del {
background: #fc0;
}
.Differences .Skipped {
background: #f7f7f7;
}
.DifferencesInline .ChangeReplace .Left,
.DifferencesInline .ChangeDelete .Left {
background: #fdd;
}
.DifferencesInline .ChangeReplace .Right,
.DifferencesInline .ChangeInsert .Right {
background: #dfd;
}
.DifferencesInline .ChangeReplace ins {
background: #9e9;
}
.DifferencesInline .ChangeReplace del {
background: #e99;
}
pre {
width: 100%;
overflow: auto;
}

View File

@@ -1,177 +0,0 @@
<?php
/**
* Diff
*
* A comprehensive library for generating differences between two strings
* in multiple formats (unified, side by side HTML etc)
*
* PHP version 5
*
* Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the Chris Boulton nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package Diff
* @author Chris Boulton <chris.boulton@interspire.com>
* @copyright (c) 2009 Chris Boulton
* @license New BSD License http://www.opensource.org/licenses/bsd-license.php
* @version 1.1
* @link http://github.com/chrisboulton/php-diff
*/
class Diff
{
/**
* @var array The "old" sequence to use as the basis for the comparison.
*/
private $a = null;
/**
* @var array The "new" sequence to generate the changes for.
*/
private $b = null;
/**
* @var array Array containing the generated opcodes for the differences between the two items.
*/
private $groupedCodes = null;
/**
* @var array Associative array of the default options available for the diff class and their default value.
*/
private $defaultOptions = array(
'context' => 3,
'ignoreNewLines' => false,
'ignoreWhitespace' => false,
'ignoreCase' => false
);
/**
* @var array Array of the options that have been applied for generating the diff.
*/
private $options = array();
/**
* The constructor.
*
* @param array $a Array containing the lines of the first string to compare.
* @param array $b Array containing the lines for the second string to compare.
* @param array $options
*/
public function __construct($a, $b, $options=array())
{
$this->a = $a;
$this->b = $b;
$this->options = array_merge($this->defaultOptions, $options);
}
/**
* Render a diff using the supplied rendering class and return it.
*
* @param Diff_Renderer_Abstract $renderer An instance of the rendering object to use for generating the diff.
* @return mixed The generated diff. Exact return value depends on the rendered.
*/
public function render(Diff_Renderer_Abstract $renderer)
{
$renderer->diff = $this;
return $renderer->render();
}
/**
* Get a range of lines from $start to $end from the first comparison string
* and return them as an array. If no values are supplied, the entire string
* is returned. It's also possible to specify just one line to return only
* that line.
*
* @param int $start The starting number.
* @param int $end The ending number. If not supplied, only the item in $start will be returned.
* @return array Array of all of the lines between the specified range.
*/
public function getA($start=0, $end=null)
{
if($start == 0 && $end === null) {
return $this->a;
}
if($end === null) {
$length = 1;
}
else {
$length = $end - $start;
}
return array_slice($this->a, $start, $length);
}
/**
* Get a range of lines from $start to $end from the second comparison string
* and return them as an array. If no values are supplied, the entire string
* is returned. It's also possible to specify just one line to return only
* that line.
*
* @param int $start The starting number.
* @param int $end The ending number. If not supplied, only the item in $start will be returned.
* @return array Array of all of the lines between the specified range.
*/
public function getB($start=0, $end=null)
{
if($start == 0 && $end === null) {
return $this->b;
}
if($end === null) {
$length = 1;
}
else {
$length = $end - $start;
}
return array_slice($this->b, $start, $length);
}
/**
* Generate a list of the compiled and grouped opcodes for the differences between the
* two strings. Generally called by the renderer, this class instantiates the sequence
* matcher and performs the actual diff generation and return an array of the opcodes
* for it. Once generated, the results are cached in the diff class instance.
*
* @return array Array of the grouped opcodes for the generated diff.
*/
public function getGroupedOpcodes()
{
if(!is_null($this->groupedCodes)) {
return $this->groupedCodes;
}
require_once dirname(__FILE__).'/Diff/SequenceMatcher.php';
$sequenceMatcher = new Diff_SequenceMatcher($this->a, $this->b, null, $this->options);
$this->groupedCodes = $sequenceMatcher->getGroupedOpcodes();
return $this->groupedCodes;
}
}

View File

@@ -1,82 +0,0 @@
<?php
/**
* Abstract class for diff renderers in PHP DiffLib.
*
* PHP version 5
*
* Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the Chris Boulton nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package DiffLib
* @author Chris Boulton <chris.boulton@interspire.com>
* @copyright (c) 2009 Chris Boulton
* @license New BSD License http://www.opensource.org/licenses/bsd-license.php
* @version 1.1
* @link http://github.com/chrisboulton/php-diff
*/
abstract class Diff_Renderer_Abstract
{
/**
* @var object Instance of the diff class that this renderer is generating the rendered diff for.
*/
public $diff;
/**
* @var array Array of the default options that apply to this renderer.
*/
protected $defaultOptions = array();
/**
* @var array Array containing the user applied and merged default options for the renderer.
*/
protected $options = array();
/**
* The constructor. Instantiates the rendering engine and if options are passed,
* sets the options for the renderer.
*
* @param array $options Optionally, an array of the options for the renderer.
*/
public function __construct(array $options = array())
{
$this->setOptions($options);
}
/**
* Set the options of the renderer to those supplied in the passed in array.
* Options are merged with the default to ensure that there aren't any missing
* options.
*
* @param array $options Array of options to set.
*/
public function setOptions(array $options)
{
$this->options = array_merge($this->defaultOptions, $options);
}
}

View File

@@ -1,225 +0,0 @@
<?php
/**
* Base renderer for rendering HTML based diffs for PHP DiffLib.
*
* PHP version 5
*
* Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the Chris Boulton nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package DiffLib
* @author Chris Boulton <chris.boulton@interspire.com>
* @copyright (c) 2009 Chris Boulton
* @license New BSD License http://www.opensource.org/licenses/bsd-license.php
* @version 1.1
* @link http://github.com/chrisboulton/php-diff
*/
require_once dirname(__FILE__).'/../Abstract.php';
class Diff_Renderer_Html_Array extends Diff_Renderer_Abstract
{
/**
* @var array Array of the default options that apply to this renderer.
*/
protected $defaultOptions = array(
'tabSize' => 4
);
/**
* Render and return an array structure suitable for generating HTML
* based differences. Generally called by subclasses that generate a
* HTML based diff and return an array of the changes to show in the diff.
*
* @return array An array of the generated chances, suitable for presentation in HTML.
*/
public function render()
{
// As we'll be modifying a & b to include our change markers,
// we need to get the contents and store them here. That way
// we're not going to destroy the original data
$a = $this->diff->getA();
$b = $this->diff->getB();
$changes = array();
$opCodes = $this->diff->getGroupedOpcodes();
foreach($opCodes as $group) {
$blocks = array();
$lastTag = null;
$lastBlock = 0;
foreach($group as $code) {
list($tag, $i1, $i2, $j1, $j2) = $code;
if($tag == 'replace' && $i2 - $i1 == $j2 - $j1) {
for($i = 0; $i < ($i2 - $i1); ++$i) {
$fromLine = $a[$i1 + $i];
$toLine = $b[$j1 + $i];
list($start, $end) = $this->getChangeExtent($fromLine, $toLine);
if($start != 0 || $end != 0) {
$last = $end + strlen($fromLine);
$fromLine = substr_replace($fromLine, "\0", $start, 0);
$fromLine = substr_replace($fromLine, "\1", $last + 1, 0);
$last = $end + strlen($toLine);
$toLine = substr_replace($toLine, "\0", $start, 0);
$toLine = substr_replace($toLine, "\1", $last + 1, 0);
$a[$i1 + $i] = $fromLine;
$b[$j1 + $i] = $toLine;
}
}
}
if($tag != $lastTag) {
$blocks[] = array(
'tag' => $tag,
'base' => array(
'offset' => $i1,
'lines' => array()
),
'changed' => array(
'offset' => $j1,
'lines' => array()
)
);
$lastBlock = count($blocks)-1;
}
$lastTag = $tag;
if($tag == 'equal') {
$lines = array_slice($a, $i1, ($i2 - $i1));
$blocks[$lastBlock]['base']['lines'] += $this->formatLines($lines);
$lines = array_slice($b, $j1, ($j2 - $j1));
$blocks[$lastBlock]['changed']['lines'] += $this->formatLines($lines);
}
else {
if($tag == 'replace' || $tag == 'delete') {
$lines = array_slice($a, $i1, ($i2 - $i1));
$lines = $this->formatLines($lines);
$lines = str_replace(array("\0", "\1"), array('<del>', '</del>'), $lines);
$blocks[$lastBlock]['base']['lines'] += $lines;
}
if($tag == 'replace' || $tag == 'insert') {
$lines = array_slice($b, $j1, ($j2 - $j1));
$lines = $this->formatLines($lines);
$lines = str_replace(array("\0", "\1"), array('<ins>', '</ins>'), $lines);
$blocks[$lastBlock]['changed']['lines'] += $lines;
}
}
}
$changes[] = $blocks;
}
return $changes;
}
/**
* Given two strings, determine where the changes in the two strings
* begin, and where the changes in the two strings end.
*
* @param string $fromLine The first string.
* @param string $toLine The second string.
* @return array Array containing the starting position (0 by default) and the ending position (-1 by default)
*/
private function getChangeExtent($fromLine, $toLine)
{
$start = 0;
$limit = min(strlen($fromLine), strlen($toLine));
while($start < $limit && $fromLine{$start} == $toLine{$start}) {
++$start;
}
$end = -1;
$limit = $limit - $start;
while(-$end <= $limit && substr($fromLine, $end, 1) == substr($toLine, $end, 1)) {
--$end;
}
return array(
$start,
$end + 1
);
}
/**
* Format a series of lines suitable for output in a HTML rendered diff.
* This involves replacing tab characters with spaces, making the HTML safe
* for output, ensuring that double spaces are replaced with &nbsp; etc.
*
* @param array $lines Array of lines to format.
* @return array Array of the formatted lines.
*/
private function formatLines($lines)
{
$lines = array_map(array($this, 'ExpandTabs'), $lines);
$lines = array_map(array($this, 'HtmlSafe'), $lines);
foreach($lines as &$line) {
$line = preg_replace_callback('# ( +)|^ #', __CLASS__."::fixSpaces", $line);
}
return $lines;
}
/**
* Replace a string containing spaces with a HTML representation using &nbsp;.
*
* @param string $matches Regex matches array.
* @return string The HTML representation of the string.
*/
public static function fixSpaces($matches)
{
$spaces = isset($matches[1]) ? $matches[1] : '';
$count = strlen($spaces);
if($count == 0) {
return '';
}
$div = floor($count / 2);
$mod = $count % 2;
return str_repeat('&nbsp; ', $div).str_repeat('&nbsp;', $mod);
}
/**
* Replace tabs in a single line with a number of spaces as defined by the tabSize option.
*
* @param string $line The containing tabs to convert.
* @return string The line with the tabs converted to spaces.
*/
private function expandTabs($line)
{
return str_replace("\t", str_repeat(' ', $this->options['tabSize']), $line);
}
/**
* Make a string containing HTML safe for output on a page.
*
* @param string $string The string.
* @return string The string with the HTML characters replaced by entities.
*/
private function htmlSafe($string)
{
return htmlspecialchars($string, ENT_NOQUOTES, 'UTF-8');
}
}

View File

@@ -1,143 +0,0 @@
<?php
/**
* Inline HTML diff generator for PHP DiffLib.
*
* PHP version 5
*
* Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the Chris Boulton nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package DiffLib
* @author Chris Boulton <chris.boulton@interspire.com>
* @copyright (c) 2009 Chris Boulton
* @license New BSD License http://www.opensource.org/licenses/bsd-license.php
* @version 1.1
* @link http://github.com/chrisboulton/php-diff
*/
require_once dirname(__FILE__).'/Array.php';
class Diff_Renderer_Html_Inline extends Diff_Renderer_Html_Array
{
/**
* Render a and return diff with changes between the two sequences
* displayed inline (under each other)
*
* @return string The generated inline diff.
*/
public function render()
{
$changes = parent::render();
$html = '';
if(empty($changes)) {
return $html;
}
$html .= '<table class="Differences DifferencesInline">';
$html .= '<thead>';
$html .= '<tr>';
$html .= '<th>Old</th>';
$html .= '<th>New</th>';
$html .= '<th>Differences</th>';
$html .= '</tr>';
$html .= '</thead>';
foreach($changes as $i => $blocks) {
// If this is a separate block, we're condensing code so output ...,
// indicating a significant portion of the code has been collapsed as
// it is the same
if($i > 0) {
$html .= '<tbody class="Skipped">';
$html .= '<th>&hellip;</th>';
$html .= '<th>&hellip;</th>';
$html .= '<td>&nbsp;</td>';
$html .= '</tbody>';
}
foreach($blocks as $change) {
$html .= '<tbody class="Change'.ucfirst($change['tag']).'">';
// Equal changes should be shown on both sides of the diff
if($change['tag'] == 'equal') {
foreach($change['base']['lines'] as $no => $line) {
$fromLine = $change['base']['offset'] + $no + 1;
$toLine = $change['changed']['offset'] + $no + 1;
$html .= '<tr>';
$html .= '<th>'.$fromLine.'</th>';
$html .= '<th>'.$toLine.'</th>';
$html .= '<td class="Left">'.$line.'</td>';
$html .= '</tr>';
}
}
// Added lines only on the right side
else if($change['tag'] == 'insert') {
foreach($change['changed']['lines'] as $no => $line) {
$toLine = $change['changed']['offset'] + $no + 1;
$html .= '<tr>';
$html .= '<th>&nbsp;</th>';
$html .= '<th>'.$toLine.'</th>';
$html .= '<td class="Right"><ins>'.$line.'</ins>&nbsp;</td>';
$html .= '</tr>';
}
}
// Show deleted lines only on the left side
else if($change['tag'] == 'delete') {
foreach($change['base']['lines'] as $no => $line) {
$fromLine = $change['base']['offset'] + $no + 1;
$html .= '<tr>';
$html .= '<th>'.$fromLine.'</th>';
$html .= '<th>&nbsp;</th>';
$html .= '<td class="Left"><del>'.$line.'</del>&nbsp;</td>';
$html .= '</tr>';
}
}
// Show modified lines on both sides
else if($change['tag'] == 'replace') {
foreach($change['base']['lines'] as $no => $line) {
$fromLine = $change['base']['offset'] + $no + 1;
$html .= '<tr>';
$html .= '<th>'.$fromLine.'</th>';
$html .= '<th>&nbsp;</th>';
$html .= '<td class="Left"><span>'.$line.'</span></td>';
$html .= '</tr>';
}
foreach($change['changed']['lines'] as $no => $line) {
$toLine = $change['changed']['offset'] + $no + 1;
$html .= '<tr>';
$html .= '<th>'.$toLine.'</th>';
$html .= '<th>&nbsp;</th>';
$html .= '<td class="Right"><span>'.$line.'</span></td>';
$html .= '</tr>';
}
}
$html .= '</tbody>';
}
}
$html .= '</table>';
return $html;
}
}

View File

@@ -1,163 +0,0 @@
<?php
/**
* Side by Side HTML diff generator for PHP DiffLib.
*
* PHP version 5
*
* Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the Chris Boulton nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package DiffLib
* @author Chris Boulton <chris.boulton@interspire.com>
* @copyright (c) 2009 Chris Boulton
* @license New BSD License http://www.opensource.org/licenses/bsd-license.php
* @version 1.1
* @link http://github.com/chrisboulton/php-diff
*/
require_once dirname(__FILE__).'/Array.php';
class Diff_Renderer_Html_SideBySide extends Diff_Renderer_Html_Array
{
/**
* Render a and return diff with changes between the two sequences
* displayed side by side.
*
* @return string The generated side by side diff.
*/
public function render()
{
$changes = parent::render();
$html = '';
if(empty($changes)) {
return $html;
}
$html .= '<table class="Differences DifferencesSideBySide">';
$html .= '<thead>';
$html .= '<tr>';
$html .= '<th colspan="2">Old Version</th>';
$html .= '<th colspan="2">New Version</th>';
$html .= '</tr>';
$html .= '</thead>';
foreach($changes as $i => $blocks) {
if($i > 0) {
$html .= '<tbody class="Skipped">';
$html .= '<th>&hellip;</th><td>&nbsp;</td>';
$html .= '<th>&hellip;</th><td>&nbsp;</td>';
$html .= '</tbody>';
}
foreach($blocks as $change) {
$html .= '<tbody class="Change'.ucfirst($change['tag']).'">';
// Equal changes should be shown on both sides of the diff
if($change['tag'] == 'equal') {
foreach($change['base']['lines'] as $no => $line) {
$fromLine = $change['base']['offset'] + $no + 1;
$toLine = $change['changed']['offset'] + $no + 1;
$html .= '<tr>';
$html .= '<th>'.$fromLine.'</th>';
$html .= '<td class="Left"><span>'.$line.'</span>&nbsp;</span></td>';
$html .= '<th>'.$toLine.'</th>';
$html .= '<td class="Right"><span>'.$line.'</span>&nbsp;</span></td>';
$html .= '</tr>';
}
}
// Added lines only on the right side
else if($change['tag'] == 'insert') {
foreach($change['changed']['lines'] as $no => $line) {
$toLine = $change['changed']['offset'] + $no + 1;
$html .= '<tr>';
$html .= '<th>&nbsp;</th>';
$html .= '<td class="Left">&nbsp;</td>';
$html .= '<th>'.$toLine.'</th>';
$html .= '<td class="Right"><ins>'.$line.'</ins>&nbsp;</td>';
$html .= '</tr>';
}
}
// Show deleted lines only on the left side
else if($change['tag'] == 'delete') {
foreach($change['base']['lines'] as $no => $line) {
$fromLine = $change['base']['offset'] + $no + 1;
$html .= '<tr>';
$html .= '<th>'.$fromLine.'</th>';
$html .= '<td class="Left"><del>'.$line.'</del>&nbsp;</td>';
$html .= '<th>&nbsp;</th>';
$html .= '<td class="Right">&nbsp;</td>';
$html .= '</tr>';
}
}
// Show modified lines on both sides
else if($change['tag'] == 'replace') {
if(count($change['base']['lines']) >= count($change['changed']['lines'])) {
foreach($change['base']['lines'] as $no => $line) {
$fromLine = $change['base']['offset'] + $no + 1;
$html .= '<tr>';
$html .= '<th>'.$fromLine.'</th>';
$html .= '<td class="Left"><span>'.$line.'</span>&nbsp;</td>';
if(!isset($change['changed']['lines'][$no])) {
$toLine = '&nbsp;';
$changedLine = '&nbsp;';
}
else {
$toLine = $change['base']['offset'] + $no + 1;
$changedLine = '<span>'.$change['changed']['lines'][$no].'</span>';
}
$html .= '<th>'.$toLine.'</th>';
$html .= '<td class="Right">'.$changedLine.'</td>';
$html .= '</tr>';
}
}
else {
foreach($change['changed']['lines'] as $no => $changedLine) {
if(!isset($change['base']['lines'][$no])) {
$fromLine = '&nbsp;';
$line = '&nbsp;';
}
else {
$fromLine = $change['base']['offset'] + $no + 1;
$line = '<span>'.$change['base']['lines'][$no].'</span>';
}
$html .= '<tr>';
$html .= '<th>'.$fromLine.'</th>';
$html .= '<td class="Left"><span>'.$line.'</span>&nbsp;</td>';
$toLine = $change['changed']['offset'] + $no + 1;
$html .= '<th>'.$toLine.'</th>';
$html .= '<td class="Right">'.$changedLine.'</td>';
$html .= '</tr>';
}
}
}
$html .= '</tbody>';
}
}
$html .= '</table>';
return $html;
}
}

View File

@@ -1,128 +0,0 @@
<?php
/**
* Context diff generator for PHP DiffLib.
*
* PHP version 5
*
* Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the Chris Boulton nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package DiffLib
* @author Chris Boulton <chris.boulton@interspire.com>
* @copyright (c) 2009 Chris Boulton
* @license New BSD License http://www.opensource.org/licenses/bsd-license.php
* @version 1.1
* @link http://github.com/chrisboulton/php-diff
*/
require_once dirname(__FILE__).'/../Abstract.php';
class Diff_Renderer_Text_Context extends Diff_Renderer_Abstract
{
/**
* @var array Array of the different opcode tags and how they map to the context diff equivalent.
*/
private $tagMap = array(
'insert' => '+',
'delete' => '-',
'replace' => '!',
'equal' => ' '
);
/**
* Render and return a context formatted (old school!) diff file.
*
* @return string The generated context diff.
*/
public function render()
{
$diff = '';
$opCodes = $this->diff->getGroupedOpcodes();
foreach($opCodes as $group) {
$diff .= "***************\n";
$lastItem = count($group)-1;
$i1 = $group[0][1];
$i2 = $group[$lastItem][2];
$j1 = $group[0][3];
$j2 = $group[$lastItem][4];
if($i2 - $i1 >= 2) {
$diff .= '*** '.($group[0][1] + 1).','.$i2." ****\n";
}
else {
$diff .= '*** '.$i2." ****\n";
}
if($j2 - $j1 >= 2) {
$separator = '--- '.($j1 + 1).','.$j2." ----\n";
}
else {
$separator = '--- '.$j2." ----\n";
}
$hasVisible = false;
foreach($group as $code) {
if($code[0] == 'replace' || $code[0] == 'delete') {
$hasVisible = true;
break;
}
}
if($hasVisible) {
foreach($group as $code) {
list($tag, $i1, $i2, $j1, $j2) = $code;
if($tag == 'insert') {
continue;
}
$diff .= $this->tagMap[$tag].' '.implode("\n".$this->tagMap[$tag].' ', $this->diff->GetA($i1, $i2))."\n";
}
}
$hasVisible = false;
foreach($group as $code) {
if($code[0] == 'replace' || $code[0] == 'insert') {
$hasVisible = true;
break;
}
}
$diff .= $separator;
if($hasVisible) {
foreach($group as $code) {
list($tag, $i1, $i2, $j1, $j2) = $code;
if($tag == 'delete') {
continue;
}
$diff .= $this->tagMap[$tag].' '.implode("\n".$this->tagMap[$tag].' ', $this->diff->GetB($j1, $j2))."\n";
}
}
}
return $diff;
}
}

View File

@@ -1,87 +0,0 @@
<?php
/**
* Unified diff generator for PHP DiffLib.
*
* PHP version 5
*
* Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the Chris Boulton nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package DiffLib
* @author Chris Boulton <chris.boulton@interspire.com>
* @copyright (c) 2009 Chris Boulton
* @license New BSD License http://www.opensource.org/licenses/bsd-license.php
* @version 1.1
* @link http://github.com/chrisboulton/php-diff
*/
require_once dirname(__FILE__).'/../Abstract.php';
class Diff_Renderer_Text_Unified extends Diff_Renderer_Abstract
{
/**
* Render and return a unified diff.
*
* @return string The unified diff.
*/
public function render()
{
$diff = '';
$opCodes = $this->diff->getGroupedOpcodes();
foreach($opCodes as $group) {
$lastItem = count($group)-1;
$i1 = $group[0][1];
$i2 = $group[$lastItem][2];
$j1 = $group[0][3];
$j2 = $group[$lastItem][4];
if($i1 == 0 && $i2 == 0) {
$i1 = -1;
$i2 = -1;
}
$diff .= '@@ -'.($i1 + 1).','.($i2 - $i1).' +'.($j1 + 1).','.($j2 - $j1)." @@\n";
foreach($group as $code) {
list($tag, $i1, $i2, $j1, $j2) = $code;
if($tag == 'equal') {
$diff .= ' '.implode("\n ", $this->diff->GetA($i1, $i2))."\n";
}
else {
if($tag == 'replace' || $tag == 'delete') {
$diff .= '-'.implode("\n-", $this->diff->GetA($i1, $i2))."\n";
}
if($tag == 'replace' || $tag == 'insert') {
$diff .= '+'.implode("\n+", $this->diff->GetB($j1, $j2))."\n";
}
}
}
}
return $diff;
}
}

View File

@@ -1,748 +0,0 @@
<?php
/**
* Sequence matcher for Diff
*
* PHP version 5
*
* Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the Chris Boulton nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package Diff
* @author Chris Boulton <chris.boulton@interspire.com>
* @copyright (c) 2009 Chris Boulton
* @license New BSD License http://www.opensource.org/licenses/bsd-license.php
* @version 1.1
* @link http://github.com/chrisboulton/php-diff
*/
class Diff_SequenceMatcher
{
/**
* @var string|array Either a string or an array containing a callback function to determine if a line is "junk" or not.
*/
private $junkCallback = null;
/**
* @var array The first sequence to compare against.
*/
private $a = null;
/**
* @var array The second sequence.
*/
private $b = null;
/**
* @var array Array of characters that are considered junk from the second sequence. Characters are the array key.
*/
private $junkDict = array();
/**
* @var array Array of indices that do not contain junk elements.
*/
private $b2j = array();
private $options = array();
private $defaultOptions = array(
'ignoreNewLines' => false,
'ignoreWhitespace' => false,
'ignoreCase' => false
);
/**
* The constructor. With the sequences being passed, they'll be set for the
* sequence matcher and it will perform a basic cleanup & calculate junk
* elements.
*
* @param string|array $a A string or array containing the lines to compare against.
* @param string|array $b A string or array containing the lines to compare.
* @param string|array $junkCallback Either an array or string that references a callback function (if there is one) to determine 'junk' characters.
* @param array $options
*/
public function __construct($a, $b, $junkCallback=null, $options)
{
$this->a = null;
$this->b = null;
$this->junkCallback = $junkCallback;
$this->setOptions($options);
$this->setSequences($a, $b);
}
/**
* Set new options
*
* @param array $options
*/
public function setOptions($options)
{
$this->options = array_merge($this->defaultOptions, $options);
}
/**
* Set the first and second sequences to use with the sequence matcher.
*
* @param string|array $a A string or array containing the lines to compare against.
* @param string|array $b A string or array containing the lines to compare.
*/
public function setSequences($a, $b)
{
$this->setSeq1($a);
$this->setSeq2($b);
}
/**
* Set the first sequence ($a) and reset any internal caches to indicate that
* when calling the calculation methods, we need to recalculate them.
*
* @param string|array $a The sequence to set as the first sequence.
*/
public function setSeq1($a)
{
if(!is_array($a)) {
$a = str_split($a);
}
if($a == $this->a) {
return;
}
$this->a= $a;
$this->matchingBlocks = null;
$this->opCodes = null;
}
/**
* Set the second sequence ($b) and reset any internal caches to indicate that
* when calling the calculation methods, we need to recalculate them.
*
* @param string|array $b The sequence to set as the second sequence.
*/
public function setSeq2($b)
{
if(!is_array($b)) {
$b = str_split($b);
}
if($b == $this->b) {
return;
}
$this->b = $b;
$this->matchingBlocks = null;
$this->opCodes = null;
$this->fullBCount = null;
$this->chainB();
}
/**
* Generate the internal arrays containing the list of junk and non-junk
* characters for the second ($b) sequence.
*/
private function chainB()
{
$length = count ($this->b);
$this->b2j = array();
$popularDict = array();
for($i = 0; $i < $length; ++$i) {
$char = $this->b[$i];
if(isset($this->b2j[$char])) {
if($length >= 200 && count($this->b2j[$char]) * 100 > $length) {
$popularDict[$char] = 1;
unset($this->b2j[$char]);
}
else {
$this->b2j[$char][] = $i;
}
}
else {
$this->b2j[$char] = array(
$i
);
}
}
// Remove leftovers
foreach(array_keys($popularDict) as $char) {
unset($this->b2j[$char]);
}
$this->junkDict = array();
if(is_callable($this->junkCallback)) {
foreach(array_keys($popularDict) as $char) {
if(call_user_func($this->junkCallback, $char)) {
$this->junkDict[$char] = 1;
unset($popularDict[$char]);
}
}
foreach(array_keys($this->b2j) as $char) {
if(call_user_func($this->junkCallback, $char)) {
$this->junkDict[$char] = 1;
unset($this->b2j[$char]);
}
}
}
}
/**
* Checks if a particular character is in the junk dictionary
* for the list of junk characters.
* @param $b
* @return boolean True if the character is considered junk. False if not.
*/
private function isBJunk($b)
{
if(isset($this->juncDict[$b])) {
return true;
}
return false;
}
/**
* Find the longest matching block in the two sequences, as defined by the
* lower and upper constraints for each sequence. (for the first sequence,
* $alo - $ahi and for the second sequence, $blo - $bhi)
*
* Essentially, of all of the maximal matching blocks, return the one that
* startest earliest in $a, and all of those maximal matching blocks that
* start earliest in $a, return the one that starts earliest in $b.
*
* If the junk callback is defined, do the above but with the restriction
* that the junk element appears in the block. Extend it as far as possible
* by matching only junk elements in both $a and $b.
*
* @param int $alo The lower constraint for the first sequence.
* @param int $ahi The upper constraint for the first sequence.
* @param int $blo The lower constraint for the second sequence.
* @param int $bhi The upper constraint for the second sequence.
* @return array Array containing the longest match that includes the starting position in $a, start in $b and the length/size.
*/
public function findLongestMatch($alo, $ahi, $blo, $bhi)
{
$a = $this->a;
$b = $this->b;
$bestI = $alo;
$bestJ = $blo;
$bestSize = 0;
$j2Len = array();
$nothing = array();
for($i = $alo; $i < $ahi; ++$i) {
$newJ2Len = array();
$jDict = $this->arrayGetDefault($this->b2j, $a[$i], $nothing);
foreach($jDict as $jKey => $j) {
if($j < $blo) {
continue;
}
else if($j >= $bhi) {
break;
}
$k = $this->arrayGetDefault($j2Len, $j -1, 0) + 1;
$newJ2Len[$j] = $k;
if($k > $bestSize) {
$bestI = $i - $k + 1;
$bestJ = $j - $k + 1;
$bestSize = $k;
}
}
$j2Len = $newJ2Len;
}
while($bestI > $alo && $bestJ > $blo && !$this->isBJunk($b[$bestJ - 1]) &&
!$this->linesAreDifferent($bestI - 1, $bestJ - 1)) {
--$bestI;
--$bestJ;
++$bestSize;
}
while($bestI + $bestSize < $ahi && ($bestJ + $bestSize) < $bhi &&
!$this->isBJunk($b[$bestJ + $bestSize]) && !$this->linesAreDifferent($bestI + $bestSize, $bestJ + $bestSize)) {
++$bestSize;
}
while($bestI > $alo && $bestJ > $blo && $this->isBJunk($b[$bestJ - 1]) &&
!$this->isLineDifferent($bestI - 1, $bestJ - 1)) {
--$bestI;
--$bestJ;
++$bestSize;
}
while($bestI + $bestSize < $ahi && $bestJ + $bestSize < $bhi &&
$this->isBJunk($b[$bestJ + $bestSize]) && !$this->linesAreDifferent($bestI + $bestSize, $bestJ + $bestSize)) {
++$bestSize;
}
return array(
$bestI,
$bestJ,
$bestSize
);
}
/**
* Check if the two lines at the given indexes are different or not.
*
* @param int $aIndex Line number to check against in a.
* @param int $bIndex Line number to check against in b.
* @return boolean True if the lines are different and false if not.
*/
public function linesAreDifferent($aIndex, $bIndex)
{
$lineA = $this->a[$aIndex];
$lineB = $this->b[$bIndex];
if($this->options['ignoreWhitespace']) {
$replace = array("\t", ' ');
$lineA = str_replace($replace, '', $lineA);
$lineB = str_replace($replace, '', $lineB);
}
if($this->options['ignoreCase']) {
$lineA = strtolower($lineA);
$lineB = strtolower($lineB);
}
if($lineA != $lineB) {
return true;
}
return false;
}
/**
* Return a nested set of arrays for all of the matching sub-sequences
* in the strings $a and $b.
*
* Each block contains the lower constraint of the block in $a, the lower
* constraint of the block in $b and finally the number of lines that the
* block continues for.
*
* @return array Nested array of the matching blocks, as described by the function.
*/
public function getMatchingBlocks()
{
if(!empty($this->matchingBlocks)) {
return $this->matchingBlocks;
}
$aLength = count($this->a);
$bLength = count($this->b);
$queue = array(
array(
0,
$aLength,
0,
$bLength
)
);
$matchingBlocks = array();
while(!empty($queue)) {
list($alo, $ahi, $blo, $bhi) = array_pop($queue);
$x = $this->findLongestMatch($alo, $ahi, $blo, $bhi);
list($i, $j, $k) = $x;
if($k) {
$matchingBlocks[] = $x;
if($alo < $i && $blo < $j) {
$queue[] = array(
$alo,
$i,
$blo,
$j
);
}
if($i + $k < $ahi && $j + $k < $bhi) {
$queue[] = array(
$i + $k,
$ahi,
$j + $k,
$bhi
);
}
}
}
usort($matchingBlocks, array($this, 'tupleSort'));
$i1 = 0;
$j1 = 0;
$k1 = 0;
$nonAdjacent = array();
foreach($matchingBlocks as $block) {
list($i2, $j2, $k2) = $block;
if($i1 + $k1 == $i2 && $j1 + $k1 == $j2) {
$k1 += $k2;
}
else {
if($k1) {
$nonAdjacent[] = array(
$i1,
$j1,
$k1
);
}
$i1 = $i2;
$j1 = $j2;
$k1 = $k2;
}
}
if($k1) {
$nonAdjacent[] = array(
$i1,
$j1,
$k1
);
}
$nonAdjacent[] = array(
$aLength,
$bLength,
0
);
$this->matchingBlocks = $nonAdjacent;
return $this->matchingBlocks;
}
/**
* Return a list of all of the opcodes for the differences between the
* two strings.
*
* The nested array returned contains an array describing the opcode
* which includes:
* 0 - The type of tag (as described below) for the opcode.
* 1 - The beginning line in the first sequence.
* 2 - The end line in the first sequence.
* 3 - The beginning line in the second sequence.
* 4 - The end line in the second sequence.
*
* The different types of tags include:
* replace - The string from $i1 to $i2 in $a should be replaced by
* the string in $b from $j1 to $j2.
* delete - The string in $a from $i1 to $j2 should be deleted.
* insert - The string in $b from $j1 to $j2 should be inserted at
* $i1 in $a.
* equal - The two strings with the specified ranges are equal.
*
* @return array Array of the opcodes describing the differences between the strings.
*/
public function getOpCodes()
{
if(!empty($this->opCodes)) {
return $this->opCodes;
}
$i = 0;
$j = 0;
$this->opCodes = array();
$blocks = $this->getMatchingBlocks();
foreach($blocks as $block) {
list($ai, $bj, $size) = $block;
$tag = '';
if($i < $ai && $j < $bj) {
$tag = 'replace';
}
else if($i < $ai) {
$tag = 'delete';
}
else if($j < $bj) {
$tag = 'insert';
}
if($tag) {
$this->opCodes[] = array(
$tag,
$i,
$ai,
$j,
$bj
);
}
$i = $ai + $size;
$j = $bj + $size;
if($size) {
$this->opCodes[] = array(
'equal',
$ai,
$i,
$bj,
$j
);
}
}
return $this->opCodes;
}
/**
* Return a series of nested arrays containing different groups of generated
* opcodes for the differences between the strings with up to $context lines
* of surrounding content.
*
* Essentially what happens here is any big equal blocks of strings are stripped
* out, the smaller subsets of changes are then arranged in to their groups.
* This means that the sequence matcher and diffs do not need to include the full
* content of the different files but can still provide context as to where the
* changes are.
*
* @param int $context The number of lines of context to provide around the groups.
* @return array Nested array of all of the grouped opcodes.
*/
public function getGroupedOpcodes($context=3)
{
$opCodes = $this->getOpCodes();
if(empty($opCodes)) {
$opCodes = array(
array(
'equal',
0,
1,
0,
1
)
);
}
if($opCodes[0][0] == 'equal') {
$opCodes[0] = array(
$opCodes[0][0],
max($opCodes[0][1], $opCodes[0][2] - $context),
$opCodes[0][2],
max($opCodes[0][3], $opCodes[0][4] - $context),
$opCodes[0][4]
);
}
$lastItem = count($opCodes) - 1;
if($opCodes[$lastItem][0] == 'equal') {
list($tag, $i1, $i2, $j1, $j2) = $opCodes[$lastItem];
$opCodes[$lastItem] = array(
$tag,
$i1,
min($i2, $i1 + $context),
$j1,
min($j2, $j1 + $context)
);
}
$maxRange = $context * 2;
$groups = array();
$group = array();
foreach($opCodes as $code) {
list($tag, $i1, $i2, $j1, $j2) = $code;
if($tag == 'equal' && $i2 - $i1 > $maxRange) {
$group[] = array(
$tag,
$i1,
min($i2, $i1 + $context),
$j1,
min($j2, $j1 + $context)
);
$groups[] = $group;
$group = array();
$i1 = max($i1, $i2 - $context);
$j1 = max($j1, $j2 - $context);
}
$group[] = array(
$tag,
$i1,
$i2,
$j1,
$j2
);
}
if(!empty($group) && !(count($group) == 1 && $group[0][0] == 'equal')) {
$groups[] = $group;
}
return $groups;
}
/**
* Return a measure of the similarity between the two sequences.
* This will be a float value between 0 and 1.
*
* Out of all of the ratio calculation functions, this is the most
* expensive to call if getMatchingBlocks or getOpCodes is yet to be
* called. The other calculation methods (quickRatio and realquickRatio)
* can be used to perform quicker calculations but may be less accurate.
*
* The ratio is calculated as (2 * number of matches) / total number of
* elements in both sequences.
*
* @return float The calculated ratio.
*/
public function Ratio()
{
$matches = array_reduce($this->getMatchingBlocks(), array($this, 'ratioReduce'), 0);
return $this->calculateRatio($matches, count ($this->a) + count ($this->b));
}
/**
* Helper function to calculate the number of matches for Ratio().
*
* @param int $sum The running total for the number of matches.
* @param array $triple Array containing the matching block triple to add to the running total.
* @return int The new running total for the number of matches.
*/
private function ratioReduce($sum, $triple)
{
return $sum + ($triple[count($triple) - 1]);
}
/**
* Quickly return an upper bound ratio for the similarity of the strings.
* This is quicker to compute than Ratio().
*
* @return float The calculated ratio.
*/
private function quickRatio()
{
if($this->fullBCount === null) {
$this->fullBCount = array();
$bLength = count ($this->b);
for($i = 0; $i < $bLength; ++$i) {
$char = $this->b[$i];
$this->fullBCount[$char] = $this->arrayGetDefault($this->fullBCount, $char, 0) + 1;
}
}
$avail = array();
$matches = 0;
$aLength = count ($this->a);
for($i = 0; $i < $aLength; ++$i) {
$char = $this->a[$i];
if(isset($avail[$char])) {
$numb = $avail[$char];
}
else {
$numb = $this->arrayGetDefault($this->fullBCount, $char, 0);
}
$avail[$char] = $numb - 1;
if($numb > 0) {
++$matches;
}
}
$this->calculateRatio($matches, count ($this->a) + count ($this->b));
}
/**
* Return an upper bound ratio really quickly for the similarity of the strings.
* This is quicker to compute than Ratio() and quickRatio().
*
* @return float The calculated ratio.
*/
private function realquickRatio()
{
$aLength = count ($this->a);
$bLength = count ($this->b);
return $this->calculateRatio(min($aLength, $bLength), $aLength + $bLength);
}
/**
* Helper function for calculating the ratio to measure similarity for the strings.
* The ratio is defined as being 2 * (number of matches / total length)
*
* @param int $matches The number of matches in the two strings.
* @param int $length The length of the two strings.
* @return float The calculated ratio.
*/
private function calculateRatio($matches, $length=0)
{
if($length) {
return 2 * ($matches / $length);
}
else {
return 1;
}
}
/**
* Helper function that provides the ability to return the value for a key
* in an array of it exists, or if it doesn't then return a default value.
* Essentially cleaner than doing a series of if(isset()) {} else {} calls.
*
* @param array $array The array to search.
* @param string $key The key to check that exists.
* @param mixed $default The value to return as the default value if the key doesn't exist.
* @return mixed The value from the array if the key exists or otherwise the default.
*/
private function arrayGetDefault($array, $key, $default)
{
if(isset($array[$key])) {
return $array[$key];
}
else {
return $default;
}
}
/**
* Sort an array by the nested arrays it contains. Helper function for getMatchingBlocks
*
* @param array $a First array to compare.
* @param array $b Second array to compare.
* @return int -1, 0 or 1, as expected by the usort function.
*/
private function tupleSort($a, $b)
{
$max = max(count($a), count($b));
for($i = 0; $i < $max; ++$i) {
if($a[$i] < $b[$i]) {
return -1;
}
else if($a[$i] > $b[$i]) {
return 1;
}
}
if(count($a) == count($b)) {
return 0;
}
else if(count($a) < count($b)) {
return -1;
}
else {
return 1;
}
}
}

View File

@@ -1,4 +0,0 @@
* text=auto
*.bat eol=crlf
docs export-ignore

View File

@@ -1,6 +0,0 @@
*.tgz
*.phar
behat.yml
vendor
composer.lock
phpspec.phar

View File

@@ -1,26 +0,0 @@
imports:
- javascript
- php
tools:
php_code_sniffer:
filter:
excluded-paths: [ spec/*, integration/*, features/* ]
config:
standard: PSR2
php_analyzer:
filter:
excluded-paths: [ spec/*, integration/* ]
php_sim:
filter:
excluded-paths: [ spec/*, integration/* ]
build_failure_conditions:
- 'issues.label("coding-style").exists'
filter:
excluded_paths:
- docs/*
- vendor/*

View File

@@ -1,41 +0,0 @@
language: php
matrix:
include:
- php: 5.3
- php: 5.3.3
env: DEPENDENCIES='low'
SMOKE='true'
- php: 5.4
- php: 5.5
- php: 5.6
env: DEPENDENCIES='dev'
- php: 5.6
env: SMOKE='true'
- php: hhvm
env: SMOKE='true'
- php: hhvm-nightly
- php: 7.0
allow_failures:
- php: hhvm-nightly
- php: 7.0
- env: DEPENDENCIES='dev'
fast_finish: true
before_install:
- if [ "$SMOKE" == "true" ]; then sudo apt-get install expect; fi;
- composer selfupdate
install:
- export COMPOSER_ROOT_VERSION=dev-master
- if [ "$DEPENDENCIES" == "dev" ]; then perl -pi -e 's/^}$/,"minimum-stability":"dev"}/' composer.json; fi;
- if [ "$DEPENDENCIES" != "low" ]; then composer update; fi;
- if [ "$DEPENDENCIES" == "low" ]; then composer update --prefer-lowest; fi;
before_script:
- echo "<?php if (PHP_VERSION_ID >= 50400) echo ',@php5.4';" > php_version_tags.php
script:
- bin/phpspec run --format=pretty
- ./vendor/bin/phpunit --testdox
- ./vendor/bin/behat --format=pretty `if [ "$SMOKE" == "true" ]; then echo '--profile=smoke'; fi;` --tags '~@php-version'`php php_version_tags.php`

View File

@@ -1,163 +0,0 @@
2.2.0 / 2015-04-18
==================
* No changes from rc1
2.2.0-rc1 / 2015-04-13
======================
* No changes from beta2
2.2.0-beta2 / 2015-04-03
========================
* Better diffs when presenting unexpected method arguments
* Better handling of methods delclared inside Traits when faking
2.2.0-beta / 2015-03-28
=======================
* Offer to generate interfaces for missing typehinted collaborators
* Support for TAP format output
* Remove deprecated usage of Symfony DialogHelper
* New array `shouldHaveKeyWithValue` matcher
* Clearer error message when specs have incorrect namespace prefix
* Fix suite rerunning for HHVM
Backward Compatibility
----------------------
* The unused `ask` and `askAndValidate` methods on `Console\IO` have been removed
2.1.1 / 2015-01-09
==================
* Smoother rendering for progress bar
* Fixed progress bar for case where no examples are found
* Tidier output alignment + block width
* Removed deprecated calls to Yaml::parse
* More accurate lower bounds for composer installation
2.1.0 / 2014-12-14
==================
* No changes from RC3
2.1.0-RC3 / 2014-12-04
======================
* Removed minor BC break introduced in RC2
2.1.0-RC2 / 2014-11-14
======================
* Specify bootstrap file via configuration
* Correct error codes while using --stop-on-failure
* Better detection of empty specs
* Fixed issue where non-spec files in spec folder caused errors
* Better PSR-4 support
2.1.0-RC1 / 2014-09-14
======================
* Allow objects to be instantiated via static factory methods
* Automatic generation of return statements using '--fake'
* Test suite is automatically rerun when classes or methods have been generated
* Allow examples to mark themselves as skipped
* PSR-4 support
* PSR-0 locator now supports underscores correctly
* Ability to specify a custom bootstrap file using '--bootstrap' (for autoloader registration etc)
* Ability to have a personal .phpspec.yml in home folder
* Progress bar grows from left to right and flickers less
* Improved diffs for object comparison
* Throw an exception when construction method is redefined
* Non-zero exit code when dependencies are missing
* Respect exit code of commands other than 'run'
* Higher CLI verbosity levels are handled properly
* Code Generation and Stop on Failure are configurable through phpspec.yml
* Fixes for object instantiation changes in newer versions of PHP
* PHP 5.6 support
* Fixes for progress bar sometimes rounding up to 100% when not all specs passed
* Support for non-standard Composer autoloader location
* Improved hhvm support
* Extensions can now register new command
* Resource locator de-duplicates resources (supports custom locators in extensions)
2.0.1 / 2014-07-01
==================
* Fixed the loading of the autoloader for projects using a custom composer vendor folder
2.0.0 / 2014-03-19
==================
* Improve support to windows
* Improve support to hhvm
* Improve acceptance tests coverage with Behat
2.0.0-RC4 / 2014-02-21
======================
* Revamped junit formatter
* Fixed #269 Problem with exception masking and generation for not found class
* HHVM is officially supported
* Add psr0 validator
* Remove Nyan from core
* Added an exception if the specified config file does not exist
* Fixed a problem with generating a constructor when it is first time added
* Improved help
* Fixed the suite runner in fast machines
2.0.0-RC3 / 2014-01-01
======================
* Fixed the Prophecy constraint as the new release is 1.1
* Refactored formatters to be defined as services
2.0.0-RC2 / 2013-12-30
======================
* Fixed the invocation of methods expecting an argument passed by reference
* Fixed the instantiation of the wrapped object in shouldThrow
2.0.0-RC1 / 2013-12-26
======================
* Bump the Prophecy requirement to ``~1.0.5@dev``
* Added a JUnit formatter
* Added the ``--stop-on-failure`` option
* Fixed the support of the ``--no-interaction`` option
* Added more events to add extension points
* Added the number of specs in the console output
* Fixed the handling of Windows line endings in the StringEngine and in reading doc comments
* Added extension points in the template loading
* Added a constructor generator
* Added a HTML formatter
* Added a nyan cat formatter
2.0.0beta4 / 2013-05-19
=======================
* Add collaborator constructor setter
* Fix couple of bugs in Prophecy integration layer
* New (old) dot formatter
2.0.0beta3 / 2013-05-01
=======================
* Prevent loading of unexisting PHP files
* Fix typos in the error messages
2.0.0beta2 / 2013-04-30
=======================
* Bump required Prophecy version to 1.0.1
* Support non-string values with ArrayContain matcher
* Create `src` folder if does not exist
* Fix stack trace and matchers failure printing
2.0.0beta1 / 2013-04-29
=======================
* Initial release

View File

@@ -1,25 +0,0 @@
Contributing
============
PhpSpec is an open source, community-driven project. If you'd like to contribute,
feel free to do this, but remember to follow this few simple rules:
Branching strategy
-------------------
- __Always__ base your changes on the `master` branch (all new development happens here),
- When you create Pull Request, always select `master` branch as target, otherwise it
will be closed (this is selected by default).
Coverage
--------
- All classes that interact solely with the core logic should be covered by Specs
- Any infrastructure adaptors should be covered by integration tests using PHPUnit
- All features should be covered with .feature descriptions automated with Behat
Code style / Formatting
-----------------------
- All new classes must carry the standard copyright notice docblock
- All code in the `src` folder must follow the PSR-2 standard

View File

@@ -1,23 +0,0 @@
Copyright (c) 2013-2014 Konstantin Kudryashov <ever.zet@gmail.com>
Marcello Duarte <marcello.duarte@gmail.com>
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

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

View File

@@ -1,29 +0,0 @@
phpspec
=======
The main website with documentation is at `http://www.phpspec.net <http://www.phpspec.net>`_.
.. image:: https://travis-ci.org/phpspec/phpspec.svg?branch=master
:target: http://travis-ci.org/phpspec/phpspec
:alt: Master Travis Build Status
.. image:: https://scrutinizer-ci.com/g/phpspec/phpspec/badges/quality-score.png?b=master
:target: https://scrutinizer-ci.com/g/phpspec/phpspec/build-status/master
:alt: Master Scrutinizer Quality Score
Installing Dependencies
-----------------------
Dependencies are handled via `composer <http://getcomposer.org>`_::
wget -nc http://getcomposer.org/composer.phar
php composer.phar install
Developer's mailing list
------------------------
For development discussion subscribe to `phpspec-dev@googlegroups.com <mailto:phpspec-dev@googlegroups.com>`_.
Community
---------
Check out #phpspec on irc.freenode.net.

View File

@@ -1,13 +0,0 @@
default:
suites:
application:
contexts: [ ApplicationContext, FilesystemContext ]
formatters:
progress: ~
smoke:
suites:
smoke:
contexts: [ IsolatedProcessContext, FilesystemContext ]
filters: { tags: @smoke }

View File

@@ -1,26 +0,0 @@
#!/usr/bin/env php
<?php
define('PHPSPEC_VERSION', '2.2.0');
if (is_file($autoload = getcwd() . '/vendor/autoload.php')) {
require $autoload;
} elseif (is_file($autoload = getcwd() . '/../../autoload.php')) {
require $autoload;
}
if (is_file($autoload = __DIR__ . '/../vendor/autoload.php')) {
require($autoload);
} elseif (is_file($autoload = __DIR__ . '/../../../autoload.php')) {
require($autoload);
} else {
fwrite(STDERR,
'You must set up the project dependencies, run the following commands:' . PHP_EOL .
'curl -s http://getcomposer.org/installer | php' . PHP_EOL .
'php composer.phar install' . PHP_EOL
);
exit(1);
}
$app = new PhpSpec\Console\Application(PHPSPEC_VERSION);
$app->run();

View File

@@ -1,19 +0,0 @@
{
"chmod": "0755",
"directories": [
"src"
],
"files": [
"LICENSE"
],
"finder": [
{
"name": "*.php",
"exclude": ["Tests"],
"in": "vendor"
}
],
"main": "bin/phpspec",
"output": "phpspec.phar",
"stub": true
}

View File

@@ -1,64 +0,0 @@
{
"name": "phpspec/phpspec",
"description": "Specification-oriented BDD framework for PHP 5.3+",
"keywords": ["BDD", "SpecBDD", "TDD", "spec", "specification", "tests", "testing"],
"homepage": "http://phpspec.net/",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Konstantin Kudryashov",
"email": "ever.zet@gmail.com",
"homepage": "http://everzet.com"
},
{
"name": "Marcello Duarte",
"homepage": "http://marcelloduarte.net/"
}
],
"require": {
"php": ">=5.3.3",
"phpspec/prophecy": "~1.4",
"phpspec/php-diff": "~1.0.0",
"sebastian/exporter": "~1.0",
"symfony/console": "~2.3",
"symfony/event-dispatcher": "~2.1",
"symfony/finder": "~2.1",
"symfony/process": "~2.1",
"symfony/yaml": "~2.1",
"doctrine/instantiator": "^1.0.1"
},
"require-dev": {
"behat/behat": "^3.0.11",
"bossa/phpspec2-expect": "~1.0",
"symfony/filesystem": "~2.1",
"symfony/process": "~2.1",
"phpunit/phpunit": "~4.4"
},
"suggest": {
"phpspec/nyan-formatters": "~1.0 Adds Nyan formatters"
},
"autoload": {
"psr-0": {
"PhpSpec": "src/"
}
},
"autoload-dev": {
"psr-0": {
"spec\\PhpSpec": "."
}
},
"bin": ["bin/phpspec"],
"extra": {
"branch-alias": {
"dev-master": "2.2.x-dev"
}
}
}

View File

@@ -1,244 +0,0 @@
<?php
use Behat\Behat\Tester\Exception\PendingException;
use Behat\Behat\Context\Context;
use Behat\Gherkin\Node\PyStringNode;
use Behat\Gherkin\Node\TableNode;
use Fake\Prompter;
use Fake\ReRunner;
use Matcher\ApplicationOutputMatcher;
use Matcher\ExitStatusMatcher;
use Matcher\ValidJUnitXmlMatcher;
use PhpSpec\Console\Application;
use PhpSpec\Matcher\MatchersProviderInterface;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Tester\ApplicationTester;
/**
* Defines application features from the specific context.
*/
class ApplicationContext implements Context, MatchersProviderInterface
{
/**
* @var Application
*/
private $application;
/**
* @var integer
*/
private $lastExitCode;
/**
* @var ApplicationTester
*/
private $tester;
/**
* @var Prompter
*/
private $prompter;
/**
* @var ReRunner
*/
private $reRunner;
/**
* @beforeScenario
*/
public function setupApplication()
{
$this->application = new Application('2.1-dev');
$this->application->setAutoExit(false);
$this->tester = new ApplicationTester($this->application);
$this->setupReRunner();
$this->setupPrompter();
}
private function setupPrompter()
{
$this->prompter = new Prompter();
$this->application->getContainer()->set('console.prompter', $this->prompter);
}
private function setupReRunner()
{
$this->reRunner = new ReRunner;
$this->application->getContainer()->set('process.rerunner.platformspecific', $this->reRunner);
}
/**
* @Given I have started describing the :class class
* @Given I start describing the :class class
*/
public function iDescribeTheClass($class)
{
$arguments = array(
'command' => 'describe',
'class' => $class
);
expect($this->tester->run($arguments, array('interactive' => false)))->toBe(0);
}
/**
* @When I run phpspec (non interactively)
* @When I run phpspec using the :formatter format
* @When I run phpspec with the :option option
* @When /I run phpspec with option (?P<option>.*)/
* @When /I run phpspec (?P<interactive>interactively)$/
* @When /I run phpspec (?P<interactive>interactively) with the (?P<option>.*) option/
*/
public function iRunPhpspec($formatter = null, $option = null, $interactive=null)
{
$arguments = array (
'command' => 'run'
);
if ($formatter) {
$arguments['--format'] = $formatter;
}
$this->addOptionToArguments($option, $arguments);
$this->lastExitCode = $this->tester->run($arguments, array('interactive' => (bool)$interactive));
}
/**
* @When I run phpspec and answer :answer when asked if I want to generate the code
* @When I run phpspec with the option :option and (I) answer :answer when asked if I want to generate the code
*/
public function iRunPhpspecAndAnswerWhenAskedIfIWantToGenerateTheCode($answer, $option=null)
{
$arguments = array (
'command' => 'run'
);
$this->addOptionToArguments($option, $arguments);
$this->prompter->setAnswer($answer=='y');
$this->lastExitCode = $this->tester->run($arguments, array('interactive' => true));
}
/**
* @param string $option
* @param array $arguments
*/
private function addOptionToArguments($option, array &$arguments)
{
if ($option) {
if (preg_match('/(?P<option>[a-z-]+)=(?P<value>[a-z.]+)/', $option, $matches)) {
$arguments[$matches['option']] = $matches['value'];
} else {
$arguments['--' . trim($option, '"')] = true;
}
}
}
/**
* @Then I should see :output
* @Then I should see:
*/
public function iShouldSee($output)
{
expect($this->tester)->toHaveOutput((string)$output);
}
/**
* @Then I should be prompted for code generation
*/
public function iShouldBePromptedForCodeGeneration()
{
expect($this->prompter)->toHaveBeenAsked();
}
/**
* @Then I should not be prompted for code generation
*/
public function iShouldNotBePromptedForCodeGeneration()
{
expect($this->prompter)->toNotHaveBeenAsked();
}
/**
* @Then the suite should pass
*/
public function theSuiteShouldPass()
{
expect($this->lastExitCode)->toBeLike(0);
}
/**
* @Then :number example(s) should have been skipped
*/
public function exampleShouldHaveBeenSkipped($number)
{
expect($this->tester)->toHaveOutput("($number skipped)");
}
/**
* @Then :number example(s) should have been run
*/
public function examplesShouldHaveBeenRun($number)
{
expect($this->tester)->toHaveOutput("$number examples");
}
/**
* @Then the exit code should be :code
*/
public function theExitCodeShouldBe($code)
{
expect($this->lastExitCode)->toBeLike($code);
}
/**
* @Then I should see valid junit output
*/
public function iShouldSeeValidJunitOutput()
{
expect($this->tester)->toHaveOutputValidJunitXml();
}
/**
* @Then the tests should be rerun
*/
public function theTestsShouldBeRerun()
{
expect($this->reRunner)->toHaveBeenRerun();
}
/**
* @Then the tests should not be rerun
*/
public function theTestsShouldNotBeRerun()
{
expect($this->reRunner)->toNotHaveBeenRerun();
}
/**
* @Then I should be prompted with:
*/
public function iShouldBePromptedWith(PyStringNode $question)
{
expect($this->prompter)->toHaveBeenAsked((string)$question);
}
/**
* Custom matchers
*
* @return array
*/
public function getMatchers()
{
return array(
new ApplicationOutputMatcher(),
new ValidJUnitXmlMatcher()
);
}
}

View File

@@ -1,34 +0,0 @@
<?php
namespace Fake;
use PhpSpec\Console\Prompter as PrompterInterface;
class Prompter implements PrompterInterface
{
private $answer;
private $hasBeenAsked = false;
private $question;
public function setAnswer($answer)
{
$this->answer = $answer;
}
public function askConfirmation($question, $default = true)
{
$this->hasBeenAsked = true;
$this->question = $question;
return (bool)$this->answer;
}
public function hasBeenAsked($question = null)
{
if (!$question) {
return $this->hasBeenAsked;
}
return $this->hasBeenAsked
&& preg_replace('/\s+/', ' ', trim(strip_tags($this->question))) == preg_replace('/\s+/', ' ', $question) ;
}
}

View File

@@ -1,28 +0,0 @@
<?php
namespace Fake;
use PhpSpec\Process\ReRunner as BaseReRunner;
class ReRunner implements BaseReRunner
{
private $hasBeenReRun = false;
/**
* @return boolean
*/
public function isSupported()
{
return true;
}
public function reRunSuite()
{
$this->hasBeenReRun = true;
}
public function hasBeenReRun()
{
return $this->hasBeenReRun;
}
}

View File

@@ -1,107 +0,0 @@
<?php
use Behat\Behat\Tester\Exception\PendingException;
use Behat\Behat\Context\Context;
use Behat\Gherkin\Node\PyStringNode;
use Behat\Gherkin\Node\TableNode;
use Matcher\FileExistsMatcher;
use Matcher\FileHasContentsMatcher;
use PhpSpec\Matcher\MatchersProviderInterface;
use Symfony\Component\Filesystem\Filesystem;
/**
* Defines application features from the specific context.
*/
class FilesystemContext implements Context, MatchersProviderInterface
{
/**
* @var string
*/
private $workingDirectory;
/**
* @var Filesystem
*/
private $filesystem;
public function __construct()
{
$this->filesystem = new Filesystem();
}
/**
* @beforeScenario
*/
public function prepWorkingDirectory()
{
$this->workingDirectory = tempnam(sys_get_temp_dir(), 'phpspec-behat');
$this->filesystem->remove($this->workingDirectory);
$this->filesystem->mkdir($this->workingDirectory);
chdir($this->workingDirectory);
}
/**
* @afterScenario
*/
public function removeWorkingDirectory()
{
$this->filesystem->remove($this->workingDirectory);
}
/**
* @Given the bootstrap file :file contains:
*/
public function theFileContains($file, PyStringNode $contents)
{
$this->filesystem->dumpFile($file, (string)$contents);
}
/**
* @Given the class file :file contains:
* @Given the spec file :file contains:
* @Given the trait file :file contains:
*/
public function theClassOrTraitOrSpecFileContains($file, PyStringNode $contents)
{
$this->theFileContains($file, $contents);
require_once($file);
}
/**
* @Given the config file contains:
*/
public function theConfigFileContains(PyStringNode $contents)
{
$this->theFileContains('phpspec.yml', $contents);
}
/**
* @Given there is no file :file
*/
public function thereIsNoFile($file)
{
expect($file)->toNotExist();
expect(file_exists($file))->toBe(false);
}
/**
* @Then the class in :file should contain:
* @Then a new class/spec should be generated in the :file:
*/
public function theFileShouldContain($file, PyStringNode $contents)
{
expect($file)->toExist();
expect($file)->toHaveContents($contents);
}
/**
* @return array
*/
public function getMatchers()
{
return array(
new FileExistsMatcher(),
new FileHasContentsMatcher()
);
}
}

View File

@@ -1,76 +0,0 @@
<?php
use Behat\Behat\Tester\Exception\PendingException;
use Behat\Behat\Context\Context;
use Behat\Behat\Context\SnippetAcceptingContext;
use Behat\Gherkin\Node\PyStringNode;
use Behat\Gherkin\Node\TableNode;
use Symfony\Component\Process\Process;
/**
* Defines application features from the specific context.
*/
class IsolatedProcessContext implements Context, SnippetAcceptingContext
{
private $lastOutput;
/**
* @beforeSuite
*/
public static function checkDependencies()
{
chdir(sys_get_temp_dir());
if (!@`which expect`) {
throw new \Exception('Smoke tests require the `expect` command line application');
}
}
/**
* @Given I have started describing the :class class
*/
public function iHaveStartedDescribingTheClass($class)
{
$process = new Process($this->buildPhpSpecCmd() . ' describe '. escapeshellarg($class));
$process->run();
expect($process->getExitCode())->toBe(0);
}
/**
* @When I run phpspec and answer :answer when asked if I want to generate the code
*/
public function iRunPhpspecAndAnswerWhenAskedIfIWantToGenerateTheCode($answer)
{
$process = new Process(
"exec expect -c '\n" .
"set timeout 10\n" .
"spawn {$this->buildPhpSpecCmd()} run\n" .
"expect \"Y/n\"\n" .
"send \"$answer\n\"\n" .
"expect \"Y/n\"\n" .
"interact\n" .
"'"
);
$process->run();
$this->lastOutput = $process->getOutput();
expect((bool)$process->getErrorOutput())->toBe(false);
}
/**
* @return string
*/
protected function buildPhpSpecCmd()
{
return escapeshellcmd(__DIR__ . '/../../bin/phpspec');
}
/**
* @Then the tests should be rerun
*/
public function theTestsShouldBeRerun()
{
expect(substr_count($this->lastOutput, 'for you?'))->toBe(2);
}
}

View File

@@ -1,74 +0,0 @@
<?php
namespace Matcher;
use PhpSpec\Exception\Example\FailureException;
use PhpSpec\Matcher\MatcherInterface;
use Symfony\Component\Console\Tester\ApplicationTester;
class ApplicationOutputMatcher implements MatcherInterface
{
/**
* Checks if matcher supports provided subject and matcher name.
*
* @param string $name
* @param mixed $subject
* @param array $arguments
*
* @return Boolean
*/
public function supports($name, $subject, array $arguments)
{
return ($name == 'haveOutput' && $subject instanceof ApplicationTester);
}
/**
* Evaluates positive match.
*
* @param string $name
* @param mixed $subject
* @param array $arguments
*/
public function positiveMatch($name, $subject, array $arguments)
{
$expected = $this->normalize($arguments[0]);
$actual = $this->normalize($subject->getDisplay());
if (strpos($actual, $expected) === false) {
throw new FailureException(sprintf(
"Application output did not contain expected '%s'. Actual output:\n'%s'" ,
$expected,
$subject->getDisplay()
));
}
}
private function normalize($string)
{
$string = preg_replace('/\([0-9]+ms\)/', '', $string);
return $string;
}
/**
* Evaluates negative match.
*
* @param string $name
* @param mixed $subject
* @param array $arguments
*/
public function negativeMatch($name, $subject, array $arguments)
{
throw new FailureException('Negative application output matcher not implemented');
}
/**
* Returns matcher priority.
*
* @return integer
*/
public function getPriority()
{
return 51;
}
}

View File

@@ -1,67 +0,0 @@
<?php
namespace Matcher;
use PhpSpec\Exception\Example\FailureException;
use PhpSpec\Matcher\MatcherInterface;
class FileExistsMatcher implements MatcherInterface
{
/**
* Checks if matcher supports provided subject and matcher name.
*
* @param string $name
* @param mixed $subject
* @param array $arguments
*
* @return Boolean
*/
public function supports($name, $subject, array $arguments)
{
return ('exist' == $name && is_string($subject));
}
/**
* Evaluates positive match.
*
* @param string $name
* @param mixed $subject
* @param array $arguments
*/
public function positiveMatch($name, $subject, array $arguments)
{
if (!file_exists($subject)) {
throw new FailureException(sprintf(
"File did not exist at path '%s'",
$subject
));
}
}
/**
* Evaluates negative match.
*
* @param string $name
* @param mixed $subject
* @param array $arguments
*/
public function negativeMatch($name, $subject, array $arguments)
{
if (file_exists($subject)) {
throw new FailureException(sprintf(
"File unexpectedly exists at path '%s'",
$subject
));
}
}
/**
* Returns matcher priority.
*
* @return integer
*/
public function getPriority()
{
return 0;
}
}

View File

@@ -1,66 +0,0 @@
<?php
namespace Matcher;
use PhpSpec\Exception\Example\FailureException;
use PhpSpec\Matcher\MatcherInterface;
class FileHasContentsMatcher implements MatcherInterface
{
/**
* Checks if matcher supports provided subject and matcher name.
*
* @param string $name
* @param mixed $subject
* @param array $arguments
*
* @return Boolean
*/
public function supports($name, $subject, array $arguments)
{
return ('haveContents' == $name && is_string($subject));
}
/**
* Evaluates positive match.
*
* @param string $name
* @param mixed $subject
* @param array $arguments
*/
public function positiveMatch($name, $subject, array $arguments)
{
$path = $subject;
$expectedContents = $arguments[0];
if ($expectedContents != file_get_contents($path)) {
throw new FailureException(sprintf(
"File at '%s' did not contain expected contents.\nExpected: '%s'\nActual: '%s'",
$path,
$expectedContents,
file_get_contents($path)
));
}
}
/**
* Evaluates negative match.
*
* @param string $name
* @param mixed $subject
* @param array $arguments
*/
public function negativeMatch($name, $subject, array $arguments)
{
throw new FailureException('Negative file contents matcher not implemented');
}
/**
* Returns matcher priority.
*
* @return integer
*/
public function getPriority()
{
return 51;
}
}

View File

@@ -1,66 +0,0 @@
<?php
namespace Matcher;
use PhpSpec\Exception\Example\FailureException;
use PhpSpec\Matcher\MatcherInterface;
use Symfony\Component\Console\Tester\ApplicationTester;
const JUNIT_XSD_PATH = '/src/PhpSpec/Resources/schema/junit.xsd';
class ValidJUnitXmlMatcher implements MatcherInterface
{
/**
* Checks if matcher supports provided subject and matcher name.
*
* @param string $name
* @param mixed $subject
* @param array $arguments
*
* @return Boolean
*/
public function supports($name, $subject, array $arguments)
{
return ($name == 'haveOutputValidJunitXml' && $subject instanceof ApplicationTester);
}
/**
* Evaluates positive match.
*
* @param string $name
* @param mixed $subject
* @param array $arguments
*/
public function positiveMatch($name, $subject, array $arguments)
{
$dom = new \DOMDocument();
$dom->loadXML($subject->getDisplay());
if (!$dom->schemaValidate(__DIR__ . '/../../..' . JUNIT_XSD_PATH)) {
throw new FailureException(sprintf(
"Output was not valid JUnit XML"
));
}
}
/**
* Evaluates negative match.
*
* @param string $name
* @param mixed $subject
* @param array $arguments
*/
public function negativeMatch($name, $subject, array $arguments)
{
throw new FailureException('Negative JUnit matcher not implemented');
}
/**
* Returns matcher priority.
*
* @return integer
*/
public function getPriority()
{
return 51;
}
}

View File

@@ -1,133 +0,0 @@
Feature: Developer generates a class
As a Developer
I want to automate creating classes
In order to avoid repetitive tasks and interruptions in development flow
@smoke
Scenario: Generating a class
Given I have started describing the "CodeGeneration/ClassExample1/Markdown" class
When I run phpspec and answer "y" when asked if I want to generate the code
Then a new class should be generated in the "src/CodeGeneration/ClassExample1/Markdown.php":
"""
<?php
namespace CodeGeneration\ClassExample1;
class Markdown
{
}
"""
@issue269
Scenario: Generating a class with psr4 prefix
Given the config file contains:
"""
suites:
behat_suite:
namespace: Behat\Tests\MyNamespace
psr4_prefix: Behat\Tests
"""
And I have started describing the "Behat/Tests/MyNamespace/Markdown" class
When I run phpspec and answer "y" when asked if I want to generate the code
Then a new class should be generated in the "src/MyNamespace/Markdown.php":
"""
<?php
namespace Behat\Tests\MyNamespace;
class Markdown
{
}
"""
@issue127
Scenario: Generating a class with PSR0 must convert classname underscores to directory separator
Given I have started describing the "CodeGeneration/ClassExample1/Text_Markdown" class
When I run phpspec and answer "y" when asked if I want to generate the code
Then a new class should be generated in the "src/CodeGeneration/ClassExample1/Text/Markdown.php":
"""
<?php
namespace CodeGeneration\ClassExample1;
class Text_Markdown
{
}
"""
@issue127
Scenario: Generating a class with PSR0 must not convert namespace underscores to directory separator
Given I have started describing the "CodeGeneration/Class_Example2/Text_Markdown" class
When I run phpspec and answer "y" when asked if I want to generate the code
Then a new class should be generated in the "src/CodeGeneration/Class_Example2/Text/Markdown.php":
"""
<?php
namespace CodeGeneration\Class_Example2;
class Text_Markdown
{
}
"""
Scenario: Generating a class when expectations on collaborator are defined
Given the spec file "spec/CodeGeneration/MethodExample2/ForgotPasswordSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\MethodExample2;
use CodeGeneration\MethodExample2\UserRepository;
use CodeGeneration\MethodExample2\User;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ForgotPasswordSpec extends ObjectBehavior
{
function it_changes_password_for_user(UserRepository $repository, User $user)
{
$repository->findOneByEmail('leszek.prabucki@gmail.com')->willReturn($user);
$user->changePassword('123')->shouldBeCalled();
$this->changePassword('leszek.prabucki@gmail.com', '123');
}
}
"""
And the class file "src/CodeGeneration/MethodExample2/User.php" contains:
"""
<?php
namespace CodeGeneration\MethodExample2;
interface User
{
public function changePassword($newPassword);
}
"""
And the class file "src/CodeGeneration/MethodExample2/UserRepository.php" contains:
"""
<?php
namespace CodeGeneration\MethodExample2;
interface UserRepository
{
public function findOneByEmail($email);
}
"""
When I run phpspec and answer "y" when asked if I want to generate the code
Then the class in "src/CodeGeneration/MethodExample2/ForgotPassword.php" should contain:
"""
<?php
namespace CodeGeneration\MethodExample2;
class ForgotPassword
{
}
"""

View File

@@ -1,121 +0,0 @@
Feature: Developer generates a collaborator
As a Developer
I want to automate creating collaborators
In order to avoid disrupting my workflow
Scenario: Being prompted but not generating a collaborator
Given the spec file "spec/CodeGeneration/CollaboratorExample1/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\CollaboratorExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use CodeGeneration\CollaboratorExample1\Parser;
class MarkdownSpec extends ObjectBehavior
{
function it_interacts_with_a_collaborator(Parser $parser)
{
$parser->willReturn(true);
}
}
"""
And the class file "src/CodeGeneration/CollaboratorExample1/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\CollaboratorExample1;
class Markdown
{
}
"""
When I run phpspec and answer "n" when asked if I want to generate the code
Then I should be prompted with:
"""
Would you like me to generate an interface
`CodeGeneration\CollaboratorExample1\Parser` for you?
[Y/n]
"""
Scenario: Asking for interface to be generated
Given the spec file "spec/CodeGeneration/CollaboratorExample2/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\CollaboratorExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use CodeGeneration\CollaboratorExample2\Parser;
class MarkdownSpec extends ObjectBehavior
{
function it_interacts_with_a_collaborator(Parser $parser)
{
$parser->willReturn(true);
}
}
"""
And the class file "src/CodeGeneration/CollaboratorExample2/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\CollaboratorExample2;
class Markdown
{
}
"""
When I run phpspec and answer "y" when asked if I want to generate the code
Then the class in "src/CodeGeneration/CollaboratorExample2/Parser.php" should contain:
"""
<?php
namespace CodeGeneration\CollaboratorExample2;
interface Parser
{
}
"""
Scenario: Not being prompted when typehint is in spec namespace
Given the spec file "spec/CodeGeneration/CollaboratorExample3/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\CollaboratorExample3;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_interacts_with_a_collaborator(Parser $parser)
{
$parser->willReturn(true);
}
}
"""
And the class file "src/CodeGeneration/CollaboratorExample3/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\CollaboratorExample3;
class Markdown
{
}
"""
When I run phpspec and answer "n" when asked if I want to generate the code
Then I should not be prompted for code generation

View File

@@ -1,266 +0,0 @@
Feature: Developer generates a collaborator's method
As a Developer
I want to automate creating collaborators' missing methods
In order to avoid disrupting my workflow
Scenario: Being prompted to generate a collaborator method based on typehints
Given the spec file "spec/CodeGeneration/CollaboratorMethodExample1/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\CollaboratorMethodExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use CodeGeneration\CollaboratorMethodExample1\Parser;
class MarkdownSpec extends ObjectBehavior
{
function it_interacts_with_a_collaborator(Parser $parser)
{
$parser->getSuccess()->willReturn(true);
}
}
"""
And the class file "src/CodeGeneration/CollaboratorMethodExample1/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\CollaboratorMethodExample1;
class Markdown
{
}
"""
And the class file "src/CodeGeneration/CollaboratorMethodExample1/Parser.php" contains:
"""
<?php
namespace CodeGeneration\CollaboratorMethodExample1;
interface Parser
{
}
"""
When I run phpspec and answer "n" when asked if I want to generate the code
Then I should be prompted with:
"""
Would you like me to generate a method signature
`CodeGeneration\CollaboratorMethodExample1\Parser::getSuccess()` for you?
[Y/n]
"""
Scenario: Being prompted to generate a collaborator method based on docblocks
Given the spec file "spec/CodeGeneration/CollaboratorMethodExample2/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\CollaboratorMethodExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
/**
* @param \CodeGeneration\CollaboratorMethodExample2\Parser $parser
*/
function it_interacts_with_a_collaborator($parser)
{
$parser->getSuccess()->willReturn(true);
}
}
"""
And the class file "src/CodeGeneration/CollaboratorMethodExample2/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\CollaboratorMethodExample2;
class Markdown
{
}
"""
And the class file "src/CodeGeneration/CollaboratorMethodExample2/Parser.php" contains:
"""
<?php
namespace CodeGeneration\CollaboratorMethodExample2;
interface Parser
{
}
"""
When I run phpspec and answer "n" when asked if I want to generate the code
Then I should be prompted with:
"""
Would you like me to generate a method signature
`CodeGeneration\CollaboratorMethodExample2\Parser::getSuccess()` for you?
[Y/n]
"""
Scenario: Asking for the method signature to be generated
Given the spec file "spec/CodeGeneration/CollaboratorMethodExample3/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\CollaboratorMethodExample3;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use CodeGeneration\CollaboratorMethodExample3\Parser;
class MarkdownSpec extends ObjectBehavior
{
function it_interacts_with_a_collaborator(Parser $parser)
{
$parser->getSuccess()->willReturn(true);
}
}
"""
And the class file "src/CodeGeneration/CollaboratorMethodExample3/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\CollaboratorMethodExample3;
class Markdown
{
}
"""
And the class file "src/CodeGeneration/CollaboratorMethodExample3/Parser.php" contains:
"""
<?php
namespace CodeGeneration\CollaboratorMethodExample3;
interface Parser
{
}
"""
When I run phpspec and answer "y" when asked if I want to generate the code
Then the class in "src/CodeGeneration/CollaboratorMethodExample3/Parser.php" should contain:
"""
<?php
namespace CodeGeneration\CollaboratorMethodExample3;
interface Parser
{
public function getSuccess();
}
"""
Scenario: Asking for the method signature to be generated with multiple parameters
Given the spec file "spec/CodeGeneration/CollaboratorMethodExample4/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\CollaboratorMethodExample4;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use CodeGeneration\CollaboratorMethodExample4\Parser;
class MarkdownSpec extends ObjectBehavior
{
function it_interacts_with_a_collaborator(Parser $parser)
{
$parser->parse('xyz', 2)->willReturn(1);
}
}
"""
And the class file "src/CodeGeneration/CollaboratorMethodExample4/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\CollaboratorMethodExample4;
class Markdown
{
}
"""
And the class file "src/CodeGeneration/CollaboratorMethodExample4/Parser.php" contains:
"""
<?php
namespace CodeGeneration\CollaboratorMethodExample4;
interface Parser
{
}
"""
When I run phpspec and answer "y" when asked if I want to generate the code
Then the class in "src/CodeGeneration/CollaboratorMethodExample4/Parser.php" should contain:
"""
<?php
namespace CodeGeneration\CollaboratorMethodExample4;
interface Parser
{
public function parse($argument1, $argument2);
}
"""
Scenario: Not being prompted when collaborator is a class
Given the spec file "spec/CodeGeneration/CollaboratorMethodExample5/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\CollaboratorMethodExample5;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use CodeGeneration\CollaboratorMethodExample5\Parser;
class MarkdownSpec extends ObjectBehavior
{
function it_interacts_with_a_collaborator(Parser $parser)
{
$parser->getSuccess()->willReturn(true);
}
}
"""
And the class file "src/CodeGeneration/CollaboratorMethodExample5/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\CollaboratorMethodExample5;
class Markdown
{
}
"""
And the class file "src/CodeGeneration/CollaboratorMethodExample5/Parser.php" contains:
"""
<?php
namespace CodeGeneration\CollaboratorMethodExample5;
class Parser
{
}
"""
When I run phpspec and answer "n" when asked if I want to generate the code
Then I should not be prompted for code generation

View File

@@ -1,106 +0,0 @@
Feature: Developer generates a method
As a Developer
I want to automate creating methods
In order to avoid repetitive tasks and interruptions in development flow
Scenario: Generating a method
Given the spec file "spec/CodeGeneration/MethodExample1/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\MethodExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
}
"""
And the class file "src/CodeGeneration/MethodExample1/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\MethodExample1;
class Markdown
{
}
"""
When I run phpspec and answer "y" when asked if I want to generate the code
Then the class in "src/CodeGeneration/MethodExample1/Markdown.php" should contain:
"""
<?php
namespace CodeGeneration\MethodExample1;
class Markdown
{
public function toHtml($argument1)
{
// TODO: write logic here
}
}
"""
Scenario: Generating a method in a class with psr4 prefix
Given the spec file "spec/MyNamespace/PrefixSpec.php" contains:
"""
<?php
namespace spec\Behat\Tests\MyNamespace;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class PrefixSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
}
"""
And the config file contains:
"""
suites:
behat_suite:
namespace: Behat\Tests\MyNamespace
psr4_prefix: Behat\Tests
"""
And the class file "src/MyNamespace/Prefix.php" contains:
"""
<?php
namespace Behat\Tests\MyNamespace;
class Prefix
{
}
"""
When I run phpspec and answer "y" when asked if I want to generate the code
Then the class in "src/MyNamespace/Prefix.php" should contain:
"""
<?php
namespace Behat\Tests\MyNamespace;
class Prefix
{
public function toHtml($argument1)
{
// TODO: write logic here
}
}
"""

View File

@@ -1,285 +0,0 @@
Feature: Developer generates a named constructor
As a Developer
I want to automate creating named constructor
In order to avoid repetitive tasks and interruptions in development flow
Scenario: Generating a named constructor in an empty class
Given the spec file "spec/CodeGeneration/NamedConstructor/UserSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\NamedConstructor;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class UserSpec extends ObjectBehavior
{
function it_registers_a_user()
{
$this->beConstructedThrough('register', array('firstname', 'lastname'));
$this->getFirstname()->shouldBe('firstname');
}
}
"""
And the class file "src/CodeGeneration/NamedConstructor/User.php" contains:
"""
<?php
namespace CodeGeneration\NamedConstructor;
class User
{
}
"""
When I run phpspec and answer "y" when asked if I want to generate the code
Then the class in "src/CodeGeneration/NamedConstructor/User.php" should contain:
"""
<?php
namespace CodeGeneration\NamedConstructor;
class User
{
public static function register($argument1, $argument2)
{
$user = new User();
// TODO: write logic here
return $user;
}
}
"""
Scenario: Generating a named constructor with more arguments than an existing constructor accepts
Given the spec file "spec/CodeGeneration/NamedConstructor/TooManyArguments/UserSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\NamedConstructor\TooManyArguments;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class UserSpec extends ObjectBehavior
{
function it_registers_a_user()
{
$this->beConstructedThrough('register', array('firstname', 'lastname'));
$this->getFirstname()->shouldBe('firstname');
}
}
"""
And the class file "src/CodeGeneration/NamedConstructor/TooManyArguments/User.php" contains:
"""
<?php
namespace CodeGeneration\NamedConstructor\TooManyArguments;
class User
{
public function __construct()
{
}
}
"""
When I run phpspec and answer "y" when asked if I want to generate the code
Then the class in "src/CodeGeneration/NamedConstructor/TooManyArguments/User.php" should contain:
"""
<?php
namespace CodeGeneration\NamedConstructor\TooManyArguments;
class User
{
public function __construct()
{
}
public static function register($argument1, $argument2)
{
throw new \BadMethodCallException("Mismatch between the number of arguments of the factory method and constructor");
}
}
"""
Scenario: Generating a named constructor with less arguments than an existing constructor accepts
Given the spec file "spec/CodeGeneration/NamedConstructor/TooFewArguments/UserSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\NamedConstructor\TooFewArguments;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class UserSpec extends ObjectBehavior
{
function it_registers_a_user()
{
$this->beConstructedThrough('register', array('firstname', 'lastname'));
$this->getFirstname()->shouldBe('firstname');
}
}
"""
And the class file "src/CodeGeneration/NamedConstructor/TooFewArguments/User.php" contains:
"""
<?php
namespace CodeGeneration\NamedConstructor\TooFewArguments;
class User
{
public function __construct($argument1, $argument2, $argument3)
{
}
}
"""
When I run phpspec and answer "y" when asked if I want to generate the code
Then the class in "src/CodeGeneration/NamedConstructor/TooFewArguments/User.php" should contain:
"""
<?php
namespace CodeGeneration\NamedConstructor\TooFewArguments;
class User
{
public function __construct($argument1, $argument2, $argument3)
{
}
public static function register($argument1, $argument2)
{
throw new \BadMethodCallException("Mismatch between the number of arguments of the factory method and constructor");
}
}
"""
Scenario: Generating a named constructor with a matching number of constructor arguments
Given the spec file "spec/CodeGeneration/NamedConstructor/EqualArguments/UserSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\NamedConstructor\EqualArguments;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class UserSpec extends ObjectBehavior
{
function it_registers_a_user()
{
$this->beConstructedThrough('register', array('firstname', 'lastname'));
$this->getFirstname()->shouldBe('firstname');
}
}
"""
And the class file "src/CodeGeneration/NamedConstructor/EqualArguments/User.php" contains:
"""
<?php
namespace CodeGeneration\NamedConstructor\EqualArguments;
class User
{
public function __construct($argument1, $argument2)
{
}
}
"""
When I run phpspec and answer "y" when asked if I want to generate the code
Then the class in "src/CodeGeneration/NamedConstructor/EqualArguments/User.php" should contain:
"""
<?php
namespace CodeGeneration\NamedConstructor\EqualArguments;
class User
{
public function __construct($argument1, $argument2)
{
}
public static function register($argument1, $argument2)
{
$user = new User($argument1, $argument2);
// TODO: write logic here
return $user;
}
}
"""
Scenario: Generating a named constructor with the correct number of required constructor arguments
Given the spec file "spec/CodeGeneration/NamedConstructor/OptionalArguments/UserSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\NamedConstructor\OptionalArguments;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class UserSpec extends ObjectBehavior
{
function it_registers_a_user()
{
$this->beConstructedThrough('register', array('firstname', 'lastname'));
$this->getFirstname()->shouldBe('firstname');
}
}
"""
And the class file "src/CodeGeneration/NamedConstructor/OptionalArguments/User.php" contains:
"""
<?php
namespace CodeGeneration\NamedConstructor\OptionalArguments;
class User
{
public function __construct($argument1, $argument2, $argument3 = 'optional')
{
}
}
"""
When I run phpspec and answer "y" when asked if I want to generate the code
Then the class in "src/CodeGeneration/NamedConstructor/OptionalArguments/User.php" should contain:
"""
<?php
namespace CodeGeneration\NamedConstructor\OptionalArguments;
class User
{
public function __construct($argument1, $argument2, $argument3 = 'optional')
{
}
public static function register($argument1, $argument2)
{
$user = new User($argument1, $argument2);
// TODO: write logic here
return $user;
}
}
"""

View File

@@ -1,324 +0,0 @@
Feature: Developer generates a method returning a constant
As a Developer
I want to automate creating methods that return constants
In order to avoid having to manually write the code
Scenario: Generating a scalar return type when method exists
Given the spec file "spec/CodeGeneration/ConstantExample1/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\ConstantExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
}
"""
And the class file "src/CodeGeneration/ConstantExample1/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\ConstantExample1;
class Markdown
{
public function toHtml($argument1)
{}
}
"""
When I run phpspec with the option "fake" and answer "y" when asked if I want to generate the code
Then the class in "src/CodeGeneration/ConstantExample1/Markdown.php" should contain:
"""
<?php
namespace CodeGeneration\ConstantExample1;
class Markdown
{
public function toHtml($argument1)
{
return '<p>Hi, there</p>';
}
}
"""
Scenario: Generating a scalar return type when method contains comments
Given the spec file "spec/CodeGeneration/ConstantExample2/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\ConstantExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
}
"""
And the class file "src/CodeGeneration/ConstantExample2/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\ConstantExample2;
class Markdown
{
public function toHtml($argument1)
{
// TODO: Add Logic here
/*
This code is inactive
*/
}
}
"""
When I run phpspec with the option "fake" and answer "y" when asked if I want to generate the code
Then the class in "src/CodeGeneration/ConstantExample2/Markdown.php" should contain:
"""
<?php
namespace CodeGeneration\ConstantExample2;
class Markdown
{
public function toHtml($argument1)
{
return '<p>Hi, there</p>';
}
}
"""
Scenario: No prompt when method contains code
Given the spec file "spec/CodeGeneration/ConstantExample3/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\ConstantExample3;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
}
"""
And the class file "src/CodeGeneration/ConstantExample3/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\ConstantExample3;
class Markdown
{
public function toHtml($argument1)
{
$foo = 'bar';
}
}
"""
When I run phpspec interactively with the "fake" option
Then I should not be prompted for code generation
Scenario: No prompt when examples contradict code
Given the spec file "spec/CodeGeneration/ConstantExample4/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\ConstantExample4;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
function it_converts_more_plain_text_to_html_paragraphs()
{
$this->toHtml('Hello, there')->shouldReturn('<p>Hello, there</p>');
}
}
"""
And the class file "src/CodeGeneration/ConstantExample4/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\ConstantExample4;
class Markdown
{
public function toHtml($argument1)
{
}
}
"""
When I run phpspec interactively with the "fake" option
Then I should not be prompted for code generation
Scenario: No prompt when CLI option is not used
Given the spec file "spec/CodeGeneration/ConstantExample5/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\ConstantExample5;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
}
"""
And the class file "src/CodeGeneration/ConstantExample5/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\ConstantExample5;
class Markdown
{
public function toHtml($argument1)
{
}
}
"""
When I run phpspec interactively
Then I should not be prompted for code generation
Scenario: Prompted when CLI option is not used but config flag is set
Given the spec file "spec/CodeGeneration/ConstantExample6/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\ConstantExample6;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
}
"""
And the class file "src/CodeGeneration/ConstantExample6/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\ConstantExample6;
class Markdown
{
public function toHtml($argument1)
{
}
}
"""
And the config file contains:
"""
fake: true
"""
When I run phpspec interactively
Then I should be prompted for code generation
@php-version @php5.4
Scenario: Generating a scalar return type when method is in trait
Given the spec file "spec/CodeGeneration/ConstantExample7/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\ConstantExample7;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
}
"""
And the trait file "src/CodeGeneration/ConstantExample7/MarkdownTrait.php" contains:
"""
<?php
namespace CodeGeneration\ConstantExample7;
trait MarkdownTrait
{
public function toHtml($argument1)
{
}
}
"""
And the class file "src/CodeGeneration/ConstantExample7/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\ConstantExample7;
class Markdown
{
use MarkdownTrait;
}
"""
When I run phpspec with the option "fake" and answer "y" when asked if I want to generate the code
Then the class in "src/CodeGeneration/ConstantExample7/MarkdownTrait.php" should contain:
"""
<?php
namespace CodeGeneration\ConstantExample7;
trait MarkdownTrait
{
public function toHtml($argument1)
{
return '<p>Hi, there</p>';
}
}
"""

View File

@@ -1,97 +0,0 @@
Feature: Developer generates a spec
As a Developer
I want to automate creating specs
In order to avoid repetitive tasks and interruptions in development flow
Scenario: Generating a spec
When I start describing the "CodeGeneration/SpecExample1/Markdown" class
Then a new spec should be generated in the "spec/CodeGeneration/SpecExample1/MarkdownSpec.php":
"""
<?php
namespace spec\CodeGeneration\SpecExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('CodeGeneration\SpecExample1\Markdown');
}
}
"""
@issue127
Scenario: Generating a spec with PSR0 must convert classname underscores to directory separator
When I start describing the "CodeGeneration/SpecExample1/Text_Markdown" class
Then a new spec should be generated in the "spec/CodeGeneration/SpecExample1/Text/MarkdownSpec.php":
"""
<?php
namespace spec\CodeGeneration\SpecExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class Text_MarkdownSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('CodeGeneration\SpecExample1\Text_Markdown');
}
}
"""
@issue127
Scenario: Generating a spec with PSR0 must not convert namespace underscores to directory separator
When I start describing the "CodeGeneration/Spec_Example2/Text_Markdown" class
Then a new spec should be generated in the "spec/CodeGeneration/Spec_Example2/Text/MarkdownSpec.php":
"""
<?php
namespace spec\CodeGeneration\Spec_Example2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class Text_MarkdownSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('CodeGeneration\Spec_Example2\Text_Markdown');
}
}
"""
Scenario: Generating a spec for a class with psr4 prefix
Given the config file contains:
"""
suites:
behat_suite:
namespace: Behat\CodeGeneration
psr4_prefix: Behat\CodeGeneration
"""
When I start describing the "Behat/CodeGeneration/Markdown" class
Then a new spec should be generated in the "spec/MarkdownSpec.php":
"""
<?php
namespace spec\Behat\CodeGeneration;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('Behat\CodeGeneration\Markdown');
}
}
"""

View File

@@ -1,62 +0,0 @@
Feature: Developer generates a class
As a Developer
I want the tests to automatically rerun after code generation events
In order to avoid repetitive tasks and interruptions in development flow
@smoke
Scenario: Rerun after class generation
Given I have started describing the "CodeGeneration/RerunExample1/Markdown" class
When I run phpspec and answer "y" when asked if I want to generate the code
Then the tests should be rerun
Scenario: Rerun after method generation
Given the spec file "spec/CodeGeneration/RerunExample2/MarkdownSpec.php" contains:
"""
<?php
namespace spec\CodeGeneration\RerunExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
}
"""
And the class file "src/CodeGeneration/RerunExample2/Markdown.php" contains:
"""
<?php
namespace CodeGeneration\RerunExample2;
class Markdown
{
}
"""
When I run phpspec and answer "y" when asked if I want to generate the code
Then the tests should be rerun
Scenario: No rerun if code generation is off
Given I have started describing the "CodeGeneration/RerunExample3/Markdown" class
When I run phpspec non interactively
Then the tests should not be rerun
Scenario: No rerun if rerun flag is passed
Given I have started describing the "CodeGeneration/RerunExample4/Markdown" class
When I run phpspec with the option "no-rerun" and I answer "y" when asked if I want to generate the code
Then the tests should not be rerun
Scenario: No rerun if rerun flag is passed
Given I have started describing the "CodeGeneration/RerunExample5/Markdown" class
And the config file contains:
"""
rerun: false
"""
When I run phpspec and answer "y" when asked if I want to generate the code
Then the tests should not be rerun

View File

@@ -1,436 +0,0 @@
Feature: Developer specifies object construction
As a Developer
I want to describe how objects are constructed
In order to be able to test objects with non-trivial construction
Scenario: Class is initialised using a constructor
Given the spec file "spec/Runner/ConstructorExample1/ClassWithConstructorSpec.php" contains:
"""
<?php
namespace spec\Runner\ConstructorExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ClassWithConstructorSpec extends ObjectBehavior
{
function let(\DateTime $date)
{
$this->beConstructedWith($date);
}
function it_is_initializable()
{
$this->shouldHaveType('Runner\ConstructorExample1\ClassWithConstructor');
}
}
"""
And the class file "src/Runner/ConstructorExample1/ClassWithConstructor.php" contains:
"""
<?php
namespace Runner\ConstructorExample1;
class ClassWithConstructor
{
private $date;
public function __construct(\DateTime $date)
{
$this->date = $date;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: Class is initialized using a static factory method and a collaborator as argument
Given the spec file "spec/Runner/ConstructorExample2/ClassWithStaticFactoryMethodSpec.php" contains:
"""
<?php
namespace spec\Runner\ConstructorExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ClassWithStaticFactoryMethodSpec extends ObjectBehavior
{
function let(\DateTime $date)
{
$this->beConstructedThrough('getInstance', array($date));
}
function it_is_initializable()
{
$this->shouldHaveType('Runner\ConstructorExample2\ClassWithStaticFactoryMethod');
}
}
"""
And the class file "src/Runner/ConstructorExample2/ClassWithStaticFactoryMethod.php" contains:
"""
<?php
namespace Runner\ConstructorExample2;
class ClassWithStaticFactoryMethod
{
private $date;
public static function getInstance(\DateTime $date)
{
return new ClassWithStaticFactoryMethod($date);
}
private function __construct(\DateTime $date)
{
$this->date = $date;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: Default static constructor parameter is overridden in example
Given the spec file "spec/Runner/ConstructorExample3/ClassWithConstructorSpec.php" contains:
"""
<?php
namespace spec\Runner\ConstructorExample3;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ClassWithConstructorSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('foo');
}
function it_is_initializable()
{
$this->beConstructedWith('bar');
$this->getType()->shouldReturn('bar');
}
}
"""
And the class file "src/Runner/ConstructorExample3/ClassWithConstructor.php" contains:
"""
<?php
namespace Runner\ConstructorExample3;
class ClassWithConstructor
{
private $type;
public function __construct($type)
{
$this->type = $type;
}
public function getType()
{
return $this->type;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: Static constructor is overridden in example
Given the spec file "spec/Runner/ConstructorExample4/ClassWithStaticFactoryMethodSpec.php" contains:
"""
<?php
namespace spec\Runner\ConstructorExample4;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ClassWithStaticFactoryMethodSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedThrough('getInstanceOfType', array('foo'));
}
function it_is_initializable()
{
$this->beConstructedThrough('getInstanceOfType', array('bar'));
$this->getType()->shouldReturn('bar');
}
}
"""
And the class file "src/Runner/ConstructorExample4/ClassWithStaticFactoryMethod.php" contains:
"""
<?php
namespace Runner\ConstructorExample4;
class ClassWithStaticFactoryMethod
{
private $type;
private function __construct($type)
{
$this->type = $type;
}
public static function getInstanceOfType($type)
{
return new self($type);
}
public function getType()
{
return $this->type;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: Static constructor set in example used instead factory method set in let
Given the spec file "spec/Runner/ConstructorExample7/ClassWithStaticFactoryMethodAndConstructorSpec.php" contains:
"""
<?php
namespace spec\Runner\ConstructorExample7;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ClassWithStaticFactoryMethodAndConstructorSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedThrough('getInstanceOfType', array('foo'));
}
function it_is_initializable()
{
$this->beConstructedWith('bar');
$this->getType()->shouldReturn('bar');
$this->wasConstructedWith()->shouldReturn('__construct');
}
}
"""
And the class file "src/Runner/ConstructorExample7/ClassWithStaticFactoryMethodAndConstructor.php" contains:
"""
<?php
namespace Runner\ConstructorExample7;
class ClassWithStaticFactoryMethodAndConstructor
{
private $type;
private $wasConstructedWith;
public function __construct($type)
{
$this->type = $type;
$this->wasConstructedWith = '__construct';
}
public static function getInstanceOfType($type)
{
$created = new self($type);
$created->wasConstructedWith = 'getInstanceOfType';
return $created;
}
public function getType()
{
return $this->type;
}
public function wasConstructedWith()
{
return $this->wasConstructedWith;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: Factory method set in example used instead of constructor set in let
Given the spec file "spec/Runner/ConstructorExample8/ClassWithStaticFactoryMethodAndConstructorSpec.php" contains:
"""
<?php
namespace spec\Runner\ConstructorExample8;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ClassWithStaticFactoryMethodAndConstructorSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('bar');
$this->beConstructedThrough('getInstanceOfType', array('foo'));
}
function it_is_initializable()
{
$this->beConstructedThrough('getInstanceOfType', array('foo'));
$this->getType()->shouldReturn('foo');
$this->wasConstructedWith()->shouldReturn('getInstanceOfType');
}
}
"""
And the class file "src/Runner/ConstructorExample8/ClassWithStaticFactoryMethodAndConstructor.php" contains:
"""
<?php
namespace Runner\ConstructorExample8;
class ClassWithStaticFactoryMethodAndConstructor
{
private $type;
private $wasConstructedWith;
public function __construct($type)
{
$this->type = $type;
$this->wasConstructedWith = '__construct';
}
public static function getInstanceOfType($type)
{
$created = new self($type);
$created->wasConstructedWith = 'getInstanceOfType';
return $created;
}
public function getType()
{
return $this->type;
}
public function wasConstructedWith()
{
return $this->wasConstructedWith;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: Developer cannot redefine constructor parameters if object is already instantiated
Given the spec file "spec/Runner/ConstructorExample9/ClassWithConstructorSpec.php" contains:
"""
<?php
namespace spec\Runner\ConstructorExample9;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ClassConstructorSpec extends ObjectBehavior
{
function it_behaves_differently_depending_on_type()
{
$this->beConstructedWith('foo');
$this->getType()->shouldReturn('foo');
$this->beConstructedWith('bar');
$this->getType()->shouldReturn('bar');
}
}
"""
And the class file "src/Runner/ConstructorExample9/ClassConstructor.php" contains:
"""
<?php
namespace Runner\ConstructorExample9;
class ClassConstructor
{
public function __construct($type)
{
$this->type = $type;
}
public function getType()
{
return $this->type;
}
}
"""
When I run phpspec
Then I should see "you can not change object construction method when it is already instantiated"
Scenario: Developer cannot redefine factory method if object is already instantiated
Given the spec file "spec/Runner/ConstructorExample10/ClassWithFactoryMethodSpec.php" contains:
"""
<?php
namespace spec\Runner\ConstructorExample10;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ClassWithFactoryMethodSpec extends ObjectBehavior
{
function it_behaves_differently_depending_on_type()
{
$this->beConstructedThrough('createFoo');
$this->getType()->shouldReturn('foo');
$this->beConstructedWith('createBar');
$this->getType()->shouldReturn('bar');
}
}
"""
And the class file "src/Runner/ConstructorExample10/ClassWithFactoryMethod.php" contains:
"""
<?php
namespace Runner\ConstructorExample10;
class ClassWithFactoryMethod
{
private function __construct($type)
{
$this->type = $type;
}
public function getType()
{
return $this->type;
}
public static function createFoo()
{
return new self('foo');
}
public static function createBar()
{
return new self('bar');
}
}
"""
When I run phpspec
Then I should see "you can not change object construction method when it is already instantiated"

View File

@@ -1,48 +0,0 @@
Feature: Developer specifies exception behaviour
As a Developer
I want to be able to specify the exceptions by SUS will throw
In order to drive the design of my exception handling
Scenario: Throwing an exception during construction when beConstructedWith specifies valid parameters
Given the spec file "spec/Runner/ExceptionExample3/MarkdownSpec.php" contains:
"""
<?php
namespace spec\Runner\ExceptionExample3;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('nothrow');
}
function it_throws_an_exception_using_magic_syntax()
{
$this->shouldThrow('Exception')->during__construct('throw');
}
}
"""
And the class file "src/Runner/ExceptionExample3/Markdown.php" contains:
"""
<?php
namespace Runner\ExceptionExample3;
class Markdown
{
public function __construct($param)
{
if ($param == 'throw') {
throw new \Exception();
}
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,401 +0,0 @@
Feature: Developer is shown diffs
In order to debug failing tests
As a developer
I should be shown a detailed diff when expected values do not match
Scenario: String diffing
Given the spec file "spec/Diffs/DiffExample1/ClassWithStringsSpec.php" contains:
"""
<?php
namespace spec\Diffs\DiffExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ClassWithStringsSpec extends ObjectBehavior
{
function it_is_equal()
{
$this->getString()->shouldReturn('foo');
}
}
"""
And the class file "src/Diffs/DiffExample1/ClassWithStrings.php" contains:
"""
<?php
namespace Diffs\DiffExample1;
class ClassWithStrings
{
public function getString()
{
return 'bar';
}
}
"""
When I run phpspec with the "verbose" option
Then I should see:
"""
@@ -1,1 +1,1 @@
-foo
+bar
"""
Scenario: Array diffing
Given the spec file "spec/Diffs/DiffExample2/ClassWithArraysSpec.php" contains:
"""
<?php
namespace spec\Diffs\DiffExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ClassWithArraysSpec extends ObjectBehavior
{
function it_is_equal()
{
$this->getArray()->shouldReturn(array(
'int' => 1,
'string' => 'foo'
));
}
}
"""
And the class file "src/Diffs/DiffExample2/ClassWithArrays.php" contains:
"""
<?php
namespace Diffs\DiffExample2;
class ClassWithArrays
{
public function getArray()
{
return array(
'int' => 3,
'string' => 'bar'
);
}
}
"""
When I run phpspec with the "verbose" option
Then I should see:
"""
@@ -1,4 +1,4 @@
[
- int => 1,
- string => ""foo"...",
+ int => 3,
+ string => ""bar"...",
]
"""
Scenario: Object diffing
Given the spec file "spec/Diffs/DiffExample3/ClassWithObjectsSpec.php" contains:
"""
<?php
namespace spec\Diffs\DiffExample3;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ClassWithObjectsSpec extends ObjectBehavior
{
function it_is_equal()
{
$obj = new \StdClass;
$obj->i = 1;
$obj->s = 'foo';
$this->getObject()->shouldReturn($obj);
}
}
"""
And the class file "src/Diffs/DiffExample3/ClassWithObjects.php" contains:
"""
<?php
namespace Diffs\DiffExample3;
class ClassWithObjects
{
public function getObject()
{
$obj = new \StdClass;
$obj->i = 2;
$obj->s = 'bar';
return $obj;
}
}
"""
When I run phpspec with the "verbose" option
Then I should see:
"""
- 'i' => 1
- 's' => 'foo'
"""
And I should see:
"""
+ 'i' => 2
+ 's' => 'bar'
"""
Scenario: Unexpected method arguments call arguments string diffing
Given the spec file "spec/Diffs/DiffExample4/ClassUnderSpecificationSpec.php" contains:
"""
<?php
namespace spec\Diffs\DiffExample4;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Diffs\DiffExample4\ClassBeingMocked;
class ClassUnderSpecificationSpec extends ObjectBehavior
{
function it_can_do_work(ClassBeingMocked $objectBeingMocked)
{
$objectBeingMocked->setValue('some really really long string, and even more, and more!')->shouldBeCalled();
$this->doWork($objectBeingMocked);
}
}
"""
And the class file "src/Diffs/DiffExample4/ClassUnderSpecification.php" contains:
"""
<?php
namespace Diffs\DiffExample4;
class ClassUnderSpecification
{
public function doWork(ClassBeingMocked $objectBeingMocked)
{
$objectBeingMocked->setValue('some really really long string, and even more, and more');
}
}
"""
And the class file "src/Diffs/DiffExample4/ClassBeingMocked.php" contains:
"""
<?php
namespace Diffs\DiffExample4;
class ClassBeingMocked
{
public function setValue($value)
{
}
}
"""
When I run phpspec with the "verbose" option
Then I should see:
"""
@@ -1,1 +1,1 @@
-some really really long string, and even more, and more!
+some really really long string, and even more, and more
"""
Scenario: Unexpected method arguments call arguments array diffing
Given the spec file "spec/Diffs/DiffExample5/ClassUnderSpecificationSpec.php" contains:
"""
<?php
namespace spec\Diffs\DiffExample5;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Diffs\DiffExample5\ClassBeingMocked;
class ClassUnderSpecificationSpec extends ObjectBehavior
{
function it_can_do_work(ClassBeingMocked $objectBeingMocked)
{
$objectBeingMocked->setValue(array(
'key1' => 'val1',
'key2' => 'val2',
))->shouldBeCalled();
$this->doWork($objectBeingMocked);
}
}
"""
And the class file "src/Diffs/DiffExample5/ClassUnderSpecification.php" contains:
"""
<?php
namespace Diffs\DiffExample5;
class ClassUnderSpecification
{
public function doWork(ClassBeingMocked $objectBeingMocked)
{
$objectBeingMocked->setValue(array(
'key1' => 'val1',
'key5' => 'val5',
));
}
}
"""
And the class file "src/Diffs/DiffExample5/ClassBeingMocked.php" contains:
"""
<?php
namespace Diffs\DiffExample5;
class ClassBeingMocked
{
public function setValue($value)
{
}
}
"""
When I run phpspec with the "verbose" option
Then I should see:
"""
@@ -1,4 +1,4 @@
[
key1 => ""val1"...",
- key2 => ""val2"...",
+ key5 => ""val5"...",
]
"""
Scenario: Unexpected method arguments call with multiple arguments icluding null diffing
Given the spec file "spec/Diffs/DiffExample6/ClassUnderSpecificationSpec.php" contains:
"""
<?php
namespace spec\Diffs\DiffExample6;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Diffs\DiffExample6\ClassBeingMocked;
class ClassUnderSpecificationSpec extends ObjectBehavior
{
function it_can_do_work(ClassBeingMocked $objectBeingMocked)
{
$objectBeingMocked->setValue(array(
'key' => 'value'
), 'foo', null)->shouldBeCalled();
$this->doWork($objectBeingMocked);
}
}
"""
And the class file "src/Diffs/DiffExample6/ClassUnderSpecification.php" contains:
"""
<?php
namespace Diffs\DiffExample6;
class ClassUnderSpecification
{
public function doWork(ClassBeingMocked $objectBeingMocked)
{
$objectBeingMocked->setValue(array(
'key' => 'another value'
), 'foo', 'bar');
}
}
"""
And the class file "src/Diffs/DiffExample6/ClassBeingMocked.php" contains:
"""
<?php
namespace Diffs\DiffExample6;
class ClassBeingMocked
{
public function setValue($value)
{
}
}
"""
When I run phpspec with the "verbose" option
Then I should see:
"""
@@ -1,3 +1,3 @@
[
- key => ""value"...",
+ key => ""another value"...",
]
"""
And I should see:
"""
@@ -1,1 +1,1 @@
-null
+bar
"""
Scenario: Unexpected method call
Given the spec file "spec/Diffs/DiffExample7/ClassUnderSpecificationSpec.php" contains:
"""
<?php
namespace spec\Diffs\DiffExample7;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Diffs\DiffExample7\ClassBeingMocked;
class ClassUnderSpecificationSpec extends ObjectBehavior
{
function it_can_do_work(ClassBeingMocked $objectBeingMocked)
{
$objectBeingMocked->methodOne('value')->shouldBeCalled();
$this->doWork($objectBeingMocked);
}
}
"""
And the class file "src/Diffs/DiffExample7/ClassUnderSpecification.php" contains:
"""
<?php
namespace Diffs\DiffExample7;
class ClassUnderSpecification
{
public function doWork(ClassBeingMocked $objectBeingMocked)
{
$objectBeingMocked->methodTwo('value');
}
}
"""
And the class file "src/Diffs/DiffExample7/ClassBeingMocked.php" contains:
"""
<?php
namespace Diffs\DiffExample7;
class ClassBeingMocked
{
public function methodOne($value)
{
}
public function methodTwo($value)
{
}
}
"""
When I run phpspec with the "verbose" option
Then I should see:
"""
method call:
- methodTwo("value")
on Double\Diffs\DiffExample7\ClassBeingMocked\P13 was not expected, expected calls were:
- methodOne(exact("value"))
"""

View File

@@ -1,68 +0,0 @@
Feature: Use the JUnit formatter
In order to provide my CI tool with parsable phpspec results
As a developer
I need to be able to use a JUnit formatter
Scenario: Successfully export phpspec results in JUnit format
Given the spec file "spec/Formatter/SpecExample/MarkdownSpec.php" contains:
"""
<?php
namespace spec\Formatter\SpecExample;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
// passed
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
// pending
function it_converts_html_paragraph_to_plain_text()
{
}
// failed
function it_formats_asterik_surrounding_text_in_italic()
{
$this->toHtml('*How are you?*')->shouldReturn('<i>How are you?</i>');
}
// broken
function it_formats_empty_text()
{
$this->toHtml('')->shouldReturn('<p></p>');
}
// skipped
function it_does_some_incompatible_things()
{
throw new \PhpSpec\Exception\Example\SkippingException();
}
}
"""
And the class file "src/Formatter/SpecExample/Markdown.php" contains:
"""
<?php
namespace Formatter\SpecExample;
class Markdown
{
public function toHtml($text)
{
if (empty($text)) {
throw new \InvalidArgumentException('Text cannot be empty: &$£€<>"');
}
return sprintf('<p>%s</p>', $text);
}
}
"""
When I run phpspec using the "junit" format
Then I should see valid junit output

View File

@@ -1,88 +0,0 @@
Feature: Use the TAP formatter
So that I can get non-XML parseable results
As a Developer
I need to be able to use a TAP formatter
Scenario: A spec which causes various result states
Given the spec file "spec/Formatter/TapExample1/TapSpec.php" contains:
"""
<?php
namespace spec\Formatter\TapExample1;
use PhpSpec\ObjectBehavior;
use PhpSpec\Exception\Example\SkippingException;
class TapSpec extends ObjectBehavior
{
function it_is_most_definitely_pending()
{
}
function it_is_most_definitely_passing()
{
$this->fire('pass')->shouldReturn('pass');
}
function it_is_most_definitely_failing()
{
$this->fire('fail')->shouldReturn('pass');
}
function it_is_most_definitely_broken()
{
$this->fire('broken')->shouldReturn('pass');
}
function it_is_most_definitely_skipping()
{
throw new SkippingException('php is not installed');
}
}
"""
And the class file "src/Formatter/TapExample1/Tap.php" contains:
"""
<?php
namespace Formatter\TapExample1;
use PhpSpec\Exception\Example\ErrorException;
class Tap
{
public function fire($stuff)
{
switch ($stuff) {
case 'pass':
return 'pass';
case 'fail':
return 'fail';
case 'broken':
throw new ErrorException('error','something terrible occurred','foo.php',99);
}
}
}
"""
When I run phpspec using the "tap" format
Then I should see:
"""
TAP version 13
not ok 1 - Formatter\TapExample1\Tap: is most definitely pending # TODO todo: write pending example
---
severity: todo
...
ok 2 - Formatter\TapExample1\Tap: is most definitely passing
not ok 3 - Formatter\TapExample1\Tap: is most definitely failing
---
message: 'Expected "pass", but got "fail".'
severity: fail
...
not ok 4 - Formatter\TapExample1\Tap: is most definitely broken
---
message: 'error: something terrible occurred in foo.php line 99'
severity: fail
...
ok 5 - Formatter\TapExample1\Tap: is most definitely skipping # SKIP skipped: php is not installed
1..5
"""

View File

@@ -1,41 +0,0 @@
Feature: Developer uses array-key-value matcher
As a Developer
I want an array-key-value matcher
In order to confirm an array the expected value for a key
Scenario: "HaveKeyWithValue" alias matches using the array-key-value matcher
Given the spec file "spec/Matchers/ArrayKeyValueExample1/MovieSpec.php" contains:
"""
<?php
namespace spec\Matchers\ArrayKeyValueExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MovieSpec extends ObjectBehavior
{
function it_should_contain_jane_smith_in_the_cast()
{
$this->getCast()->shouldHaveKeyWithValue('leadRole', 'John Smith');
}
}
"""
And the class file "src/Matchers/ArrayKeyValueExample1/Movie.php" contains:
"""
<?php
namespace Matchers\ArrayKeyValueExample1;
class Movie
{
public function getCast()
{
return array('leadRole' => 'John Smith', 'supportingRole' => 'Jane Smith');
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,41 +0,0 @@
Feature: Developer uses array-contain matcher
As a Developer
I want an array-contain matcher
In order to confirm an array contains an expected value
Scenario: "Contain" alias matches using the array-contain matcher
Given the spec file "spec/Matchers/ArrayContainExample1/MovieSpec.php" contains:
"""
<?php
namespace spec\Matchers\ArrayContainExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MovieSpec extends ObjectBehavior
{
function it_should_contain_jane_smith_in_the_cast()
{
$this->getCast()->shouldContain('Jane Smith');
}
}
"""
And the class file "src/Matchers/ArrayContainExample1/Movie.php" contains:
"""
<?php
namespace Matchers\ArrayContainExample1;
class Movie
{
public function getCast()
{
return array('John Smith', 'Jane Smith');
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,44 +0,0 @@
Feature: Developer uses array-key matcher
As a Developer
I want an array-key matcher
In order to confirm an array contains an expected key
Scenario: "HaveKey" alias matches using the array-key matcher
Given the spec file "spec/Matchers/ArrayKeyExample1/MovieSpec.php" contains:
"""
<?php
namespace spec\Matchers\ArrayKeyExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MovieSpec extends ObjectBehavior
{
function it_should_have_a_release_date_for_france()
{
$this->getReleaseDates()->shouldHaveKey('France');
}
}
"""
And the class file "src/Matchers/ArrayKeyExample1/Movie.php" contains:
"""
<?php
namespace Matchers\ArrayKeyExample1;
class Movie
{
public function getReleaseDates()
{
return array(
'Australia' => '12 April 2013',
'France' => '24 April 2013',
);
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,41 +0,0 @@
Feature: Developer uses comparison matcher
As a Developer
I want a comparison matcher
In order to loosely compare a value against an expectation
Scenario: "BeLike" alias matches using comparison operator
Given the spec file "spec/Matchers/ComparisonExample1/StringCalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\ComparisonExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class StringCalculatorSpec extends ObjectBehavior
{
function it_returns_the_value_of_a_string()
{
$this->calc('5')->shouldBeLike('5');
}
}
"""
And the class file "src/Matchers/ComparisonExample1/StringCalculator.php" contains:
"""
<?php
namespace Matchers\ComparisonExample1;
class StringCalculator
{
public function calc($string)
{
return (int) $string;
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,41 +0,0 @@
Feature: Developer uses array-count matcher
As a Developer
I want an array-count matcher
In order to compare an array count against an expectation
Scenario: "HaveCount" alias matches using the array-count matcher
Given the spec file "spec/Matchers/ArrayCountExample1/CarSpec.php" contains:
"""
<?php
namespace spec\Matchers\ArrayCountExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CarSpec extends ObjectBehavior
{
function it_returns_the_number_of_wheels()
{
$this->getWheels()->shouldHaveCount(4);
}
}
"""
And the class file "src/Matchers/ArrayCountExample1/Car.php" contains:
"""
<?php
namespace Matchers\ArrayCountExample1;
class Car
{
public function getWheels()
{
return array('wheel', 'wheel', 'wheel', 'wheel');
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,448 +0,0 @@
Feature: Developer uses identity matcher
As a Developer
I want an identity matcher
In order to match the identity of a value against an expectation
Scenario: "Return" alias matching using identity operator
Given the spec file "spec/Matchers/IdentityExample1/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\IdentityExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2)->shouldReturn(3);
}
}
"""
And the class file "src/Matchers/IdentityExample1/Calculator.php" contains:
"""
<?php
namespace Matchers\IdentityExample1;
class Calculator
{
public function sum($x, $y)
{
return $x + $y;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Return" alias not matching using identity operator
Given the spec file "spec/Matchers/IdentityExample2/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\IdentityExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2)->shouldNotReturn(4);
}
}
"""
And the class file "src/Matchers/IdentityExample2/Calculator.php" contains:
"""
<?php
namespace Matchers\IdentityExample2;
class Calculator
{
public function sum($x, $y)
{
return $x + $y;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Return" alias not matching type using identity operator
Given the spec file "spec/Matchers/IdentityExample3/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\IdentityExample3;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2)->shouldNotReturn("3");
}
}
"""
And the class file "src/Matchers/IdentityExample3/Calculator.php" contains:
"""
<?php
namespace Matchers\IdentityExample3;
class Calculator
{
public function sum($x, $y)
{
return $x + $y;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Be" alias matching using identity operator
Given the spec file "spec/Matchers/IdentityExample4/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\IdentityExample4;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2)->shouldBe(3);
}
}
"""
And the class file "src/Matchers/IdentityExample4/Calculator.php" contains:
"""
<?php
namespace Matchers\IdentityExample4;
class Calculator
{
public function sum($x, $y)
{
return $x + $y;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Be" alias not matching using identity operator
Given the spec file "spec/Matchers/IdentityExample5/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\IdentityExample5;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2)->shouldNotBe(4);
}
}
"""
And the class file "src/Matchers/IdentityExample5/Calculator.php" contains:
"""
<?php
namespace Matchers\IdentityExample5;
class Calculator
{
public function sum($x, $y)
{
return $x + $y;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Be" alias not matching type using identity operator
Given the spec file "spec/Matchers/IdentityExample6/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\IdentityExample6;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2)->shouldNotBe("3");
}
}
"""
And the class file "src/Matchers/IdentityExample6/Calculator.php" contains:
"""
<?php
namespace Matchers\IdentityExample6;
class Calculator
{
public function sum($x, $y)
{
return $x + $y;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Equal" alias matching using identity operator
Given the spec file "spec/Matchers/IdentityExample7/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\IdentityExample7;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2)->shouldEqual(3);
}
}
"""
And the class file "src/Matchers/IdentityExample7/Calculator.php" contains:
"""
<?php
namespace Matchers\IdentityExample7;
class Calculator
{
public function sum($x, $y)
{
return $x + $y;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Equal" alias not matching using identity operator
Given the spec file "spec/Matchers/IdentityExample8/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\IdentityExample8;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2)->shouldNotEqual(4);
}
}
"""
And the class file "src/Matchers/IdentityExample8/Calculator.php" contains:
"""
<?php
namespace Matchers\IdentityExample8;
class Calculator
{
public function sum($x, $y)
{
return $x + $y;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Equal" alias not matching type using identity operator
Given the spec file "spec/Matchers/IdentityExample9/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\IdentityExample9;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2)->shouldNotEqual("3");
}
}
"""
And the class file "src/Matchers/IdentityExample9/Calculator.php" contains:
"""
<?php
namespace Matchers\IdentityExample9;
class Calculator
{
public function sum($x, $y)
{
return $x + $y;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "BeEqualTo" alias matching using identity operator
Given the spec file "spec/Matchers/IdentityExample10/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\IdentityExample10;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2)->shouldEqual(3);
}
}
"""
And the class file "src/Matchers/IdentityExample10/Calculator.php" contains:
"""
<?php
namespace Matchers\IdentityExample10;
class Calculator
{
public function sum($x, $y)
{
return $x + $y;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Equal" alias not matching using identity operator
Given the spec file "spec/Matchers/IdentityExample11/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\IdentityExample11;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2)->shouldNotEqual(4);
}
}
"""
And the class file "src/Matchers/IdentityExample11/Calculator.php" contains:
"""
<?php
namespace Matchers\IdentityExample11;
class Calculator
{
public function sum($x, $y)
{
return $x + $y;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Equal" alias not matching type using identity operator
Given the spec file "spec/Matchers/IdentityExample12/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\IdentityExample12;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2)->shouldNotEqual("3");
}
}
"""
And the class file "src/Matchers/IdentityExample12/Calculator.php" contains:
"""
<?php
namespace Matchers\IdentityExample12;
class Calculator
{
public function sum($x, $y)
{
return $x + $y;
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,111 +0,0 @@
Feature: Developer uses identity matcher
As a Developer
I want an inline matcher
So I can create expectations in a language closer to the domain I am describing
Scenario: Inline matcher with no argument
Given the spec file "spec/Matchers/InlineExample1/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\InlineExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2);
$this->shouldBePositive();
}
function getMatchers()
{
return array ('bePositive' => function($subject) {
return $subject->getTotal() > 0;
});
}
}
"""
And the class file "src/Matchers/InlineExample1/Calculator.php" contains:
"""
<?php
namespace Matchers\InlineExample1;
class Calculator
{
private $total;
public function sum($x, $y)
{
$this->total = $x + $y;
}
public function getTotal()
{
return $this->total;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: Inline matcher with an argument
Given the spec file "spec/Matchers/InlineExample2/CalculatorSpec.php" contains:
"""
<?php
namespace spec\Matchers\InlineExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CalculatorSpec extends ObjectBehavior
{
function it_calculates_the_sum_of_two_addends()
{
$this->sum(1, 2);
$this->shouldTotal(3);
}
function getMatchers()
{
return array ('total' => function($subject, $total) {
return $subject->getTotal() === $total;
});
}
}
"""
And the class file "src/Matchers/InlineExample2/Calculator.php" contains:
"""
<?php
namespace Matchers\InlineExample2;
class Calculator
{
private $total;
public function sum($x, $y)
{
$this->total = $x + $y;
}
public function getTotal()
{
return $this->total;
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,78 +0,0 @@
Feature: Developer uses object-state matcher
As a Developer
I want an object-state matcher
In order to validate objects against an expectation
Scenario: "Have" alias matches using the object-state matcher
Given the spec file "spec/Matchers/ObjectStateExample1/CarSpec.php" contains:
"""
<?php
namespace spec\Matchers\ObjectStateExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CarSpec extends ObjectBehavior
{
function it_returns_true_if_it_has_an_wheels()
{
$this->shouldHaveWheels();
}
}
"""
And the class file "src/Matchers/ObjectStateExample1/Car.php" contains:
"""
<?php
namespace Matchers\ObjectStateExample1;
class Car
{
public function hasWheels()
{
return true;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Be" alias matches using the object-state matcher
Given the spec file "spec/Matchers/ObjectStateExample2/CarSpec.php" contains:
"""
<?php
namespace spec\Matchers\ObjectStateExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CarSpec extends ObjectBehavior
{
function it_returns_true_if_it_is_available()
{
$this->shouldBeAvailable();
}
}
"""
And the class file "src/Matchers/ObjectStateExample2/Car.php" contains:
"""
<?php
namespace Matchers\ObjectStateExample2;
class Car
{
public function isAvailable()
{
return true;
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,53 +0,0 @@
Feature: Developer uses scalar matcher
As a Developer
I want an scalar matcher
In order to match against various scalar values against their expectations
Scenario: Scalar matching aliases match using the scalar matcher
Given the spec file "spec/Matchers/ScalarExample1/CarSpec.php" contains:
"""
<?php
namespace spec\Matchers\ScalarExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CarSpec extends ObjectBehavior
{
function it_returns_the_result()
{
$result = $this->getDetails();
$result['name']->shouldBeString();
$result['age']->shouldBeInteger();
$result['price']->shouldBeFloat();
$result['sale']->shouldBeBool();
$result['callback']->shouldBeCallable();
}
}
"""
And the class file "src/Matchers/ScalarExample1/Car.php" contains:
"""
<?php
namespace Matchers\ScalarExample1;
class Car
{
public function getDetails()
{
return array(
'name' => 'astra',
'age' => 34,
'price' => 10.99,
'sale' => true,
'callback' => function() {}
);
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,41 +0,0 @@
Feature: Developer uses string-end matcher
As a Developer
I want an string-end matcher
In order to confirm a string ends with an expected substring
Scenario: "EndsWith" alias matches using the string-end matcher
Given the spec file "spec/Matchers/StringEndExample1/MovieSpec.php" contains:
"""
<?php
namespace spec\Matchers\StringEndExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MovieSpec extends ObjectBehavior
{
function it_should_have_a_title_that_ends_with_of_oz()
{
$this->getTitle()->shouldEndWith('of Oz');
}
}
"""
And the class file "src/Matchers/StringEndExample1/Movie.php" contains:
"""
<?php
namespace Matchers\StringEndExample1;
class Movie
{
public function getTitle()
{
return 'The Wizard of Oz';
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,41 +0,0 @@
Feature: Developer uses string-regex matcher
As a Developer
I want an string-regex matcher
In order to confirm a string matches against an expected regular expression
Scenario: "Matches" alias matches using the string-regex matcher
Given the spec file "spec/Matchers/StringRegexExample1/MovieSpec.php" contains:
"""
<?php
namespace spec\Matchers\StringRegexExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MovieSpec extends ObjectBehavior
{
function it_should_have_a_title_that_contains_wizard()
{
$this->getTitle()->shouldMatch('/wizard/i');
}
}
"""
And the class file "src/Matchers/StringRegexExample1/Movie.php" contains:
"""
<?php
namespace Matchers\StringRegexExample1;
class Movie
{
public function getTitle()
{
return 'The Wizard of Oz';
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,41 +0,0 @@
Feature: Developer uses string-start matcher
As a Developer
I want an string-start matcher
In order to confirm a string starts with an expected substring
Scenario: "StartWith" alias matches using the string-start matcher
Given the spec file "spec/Matchers/StringStartExample1/MovieSpec.php" contains:
"""
<?php
namespace spec\Matchers\StringStartExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MovieSpec extends ObjectBehavior
{
function it_should_have_a_title_that_starts_with_the_wizard()
{
$this->getTitle()->shouldStartWith('The Wizard');
}
}
"""
And the class file "src/Matchers/StringStartExample1/Movie.php" contains:
"""
<?php
namespace Matchers\StringStartExample1;
class Movie
{
public function getTitle()
{
return 'The Wizard of Oz';
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,165 +0,0 @@
Feature: Developer uses throw matcher
As a Developer
I want a throw matcher
In order to validate objects exceptions against my expectations
Scenario: "Throw" alias matches using the throw matcher with explicit method name
Given the spec file "spec/Matchers/ThrowExample1/EmployeeSpec.php" contains:
"""
<?php
namespace spec\Matchers\ThrowExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class EmployeeSpec extends ObjectBehavior
{
function it_throws_an_exception_when_arguments_are_invalid()
{
$this->shouldThrow('\InvalidArgumentException')->during('setAge', array(0));
}
}
"""
And the class file "src/Matchers/ThrowExample1/Employee.php" contains:
"""
<?php
namespace Matchers\ThrowExample1;
class Employee
{
public function setAge($age)
{
if (0 === $age) {
throw new \InvalidArgumentException();
}
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Throw" alias matches using the throw matcher with implicit method name
Given the spec file "spec/Matchers/ThrowExample2/EmployeeSpec.php" contains:
"""
<?php
namespace spec\Matchers\ThrowExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class EmployeeSpec extends ObjectBehavior
{
function it_throws_an_exception_when_arguments_are_invalid()
{
$this->shouldThrow('\InvalidArgumentException')->duringSetAge(0);
}
}
"""
And the class file "src/Matchers/ThrowExample2/Employee.php" contains:
"""
<?php
namespace Matchers\ThrowExample2;
class Employee
{
public function setAge($age)
{
if (0 === $age) {
throw new \InvalidArgumentException();
}
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Throw" alias matches using the throw matcher with specific exception message
Given the spec file "spec/Matchers/ThrowExample3/EmployeeSpec.php" contains:
"""
<?php
namespace spec\Matchers\ThrowExample3;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class EmployeeSpec extends ObjectBehavior
{
function it_throws_an_exception_when_arguments_are_invalid()
{
$this->shouldThrow(new \InvalidArgumentException('Invalid age'))->duringSetAge(0);
}
}
"""
And the class file "src/Matchers/ThrowExample3/Employee.php" contains:
"""
<?php
namespace Matchers\ThrowExample3;
class Employee
{
public function setAge($age)
{
if (0 === $age) {
throw new \InvalidArgumentException('Invalid age');
}
}
}
"""
When I run phpspec
Then the suite should pass
@issue134
Scenario: Throwing an exception during object construction
Given the spec file "spec/Runner/ThrowExample4/MarkdownSpec.php" contains:
"""
<?php
namespace spec\Runner\ThrowExample4;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_throws_an_exception_using_during_syntax()
{
$this->shouldThrow('Exception')->during('__construct', array(1,2));
}
function it_throws_an_exception_using_magic_syntax()
{
$this->shouldThrow('Exception')->during__construct(1,2);
}
}
"""
And the class file "src/Runner/ThrowExample4/Markdown.php" contains:
"""
<?php
namespace Runner\ThrowExample4;
class Markdown
{
public function __construct($num1, $num2)
{
throw new \Exception();
}
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,145 +0,0 @@
Feature: Developer uses type matcher
As a Developer
I want a type matcher
In order to confirm that my object is of a given type
Scenario: "HaveType" alias matches using the type matcher
Given the spec file "spec/Matchers/TypeExample1/CarSpec.php" contains:
"""
<?php
namespace spec\Matchers\TypeExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CarSpec extends ObjectBehavior
{
function it_should_be_a_car()
{
$this->shouldHaveType('Matchers\TypeExample1\Car');
}
}
"""
And the class file "src/Matchers/TypeExample1/Car.php" contains:
"""
<?php
namespace Matchers\TypeExample1;
class Car
{
}
"""
When I run phpspec
Then the suite should pass
Scenario: "ReturnAnInstanceOf" alias matches using the type matcher
Given the spec file "spec/Matchers/TypeExample2/CarSpec.php" contains:
"""
<?php
namespace spec\Matchers\TypeExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CarSpec extends ObjectBehavior
{
function it_should_be_a_car()
{
$this->get()->shouldReturnAnInstanceOf('Matchers\TypeExample2\Car');
}
}
"""
And the class file "src/Matchers/TypeExample2/Car.php" contains:
"""
<?php
namespace Matchers\TypeExample2;
class Car
{
public function get()
{
return $this;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "BeAnInstanceOf" alias matches using the type matcher
Given the spec file "spec/Matchers/TypeExample3/CarSpec.php" contains:
"""
<?php
namespace spec\Matchers\TypeExample3;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CarSpec extends ObjectBehavior
{
function it_should_be_a_car()
{
$this->get()->shouldBeAnInstanceOf('Matchers\TypeExample3\Car');
}
}
"""
And the class file "src/Matchers/TypeExample3/Car.php" contains:
"""
<?php
namespace Matchers\TypeExample3;
class Car
{
public function get()
{
return $this;
}
}
"""
When I run phpspec
Then the suite should pass
Scenario: "Implement" alias matches using the type matcher
Given the spec file "spec/Matchers/TypeExample4/CarSpec.php" contains:
"""
<?php
namespace spec\Matchers\TypeExample4;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class CarSpec extends ObjectBehavior
{
function it_should_be_a_car()
{
$this->shouldImplement('Matchers\TypeExample4\Car');
}
}
"""
And the class file "src/Matchers/TypeExample4/Car.php" contains:
"""
<?php
namespace Matchers\TypeExample4;
class Car
{
}
"""
When I run phpspec
Then the suite should pass

View File

@@ -1,81 +0,0 @@
Feature: Developer chooses no code generation
As a Developer
I want to set the no code generation setting option
In order to specify how phpspec behaves when a class is not found
@issue352
Scenario: code-generation defaults to off
Given the spec file "spec/NoCodeGeneration/SpecExample1/NewClassSpec.php" contains:
"""
<?php
namespace spec\NoCodeGeneration\SpecExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class NewClassSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldBeAnInstanceOf('NoCodeGeneration\NewClass');
}
}
"""
When I run phpspec interactively
Then I should be prompted for code generation
@issue352
Scenario: code-generation is specified in the config
Given the config file contains:
"""
code_generation: false
"""
And the spec file "spec/NoCodeGeneration/SpecExample2/NewClassSpec.php" contains:
"""
<?php
namespace spec\NoCodeGeneration\SpecExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class NewClassSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldBeAnInstanceOf('NoCodeGeneration\NewClass');
}
}
"""
When I run phpspec interactively
Then I should not be prompted for code generation
@issue352
Scenario: code-generation on the command line takes priority
Given the config file contains:
"""
code_generation: true
"""
And the spec file "spec/NoCodeGeneration/SpecExample3/NewClassSpec.php" contains:
"""
<?php
namespace spec\NoCodeGeneration\SpecExample3;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class NewClassSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldBeAnInstanceOf('NoCodeGeneration\NewClass');
}
}
"""
When I run phpspec interactively with the "no-code-generation" option
Then I should not be prompted for code generation

View File

@@ -1,144 +0,0 @@
Feature: Developer chooses stop on failure
As a Developer
I want to set the stop on failure setting option
In order to specify how phpspec behaves on failure
@issue352
Scenario: stop-on-failure defaults to off
Given the spec file "spec/SkipOnFailure/SpecExample1/FirstFailSpec.php" contains:
"""
<?php
namespace spec\SkipOnFailure\SpecExample1;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class FirstFailSpec extends ObjectBehavior
{
function it_fails()
{
$this->getValue()->shouldReturn(2);
}
function it_should_never_get_called()
{
$this->getValue()->shouldReturn(1);
}
}
"""
And the class file "src/SkipOnFailure/SpecExample1/FirstFail.php" contains:
"""
<?php
namespace SkipOnFailure\SpecExample1;
class FirstFail
{
public function getValue()
{
return 1;
}
}
"""
When I run phpspec
Then 2 examples should have been run
@issue352
Scenario: stop-on-failure is specified in the config
Given the config file contains:
"""
stop_on_failure: true
"""
And the spec file "spec/SkipOnFailure/SpecExample2/FirstFailSpec.php" contains:
"""
<?php
namespace spec\SkipOnFailure\SpecExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class FirstFailSpec extends ObjectBehavior
{
function it_fails()
{
$this->getValue()->shouldReturn(2);
}
function it_should_never_get_called()
{
$this->getValue()->shouldReturn(1);
}
}
"""
And the class file "src/SkipOnFailure/SpecExample2/FirstFail.php" contains:
"""
<?php
namespace SkipOnFailure\SpecExample2;
class FirstFail
{
public function getValue()
{
return 1;
}
}
"""
When I run phpspec
Then 1 example should have been run
And the exit code should be 1
@issue352
Scenario: stop-on-failure at command line overrides config
Given the config file contains:
"""
stop_on_failure: false
"""
And the spec file "spec/SkipOnFailure/SpecExample3/FirstFailSpec.php" contains:
"""
<?php
namespace spec\SkipOnFailure\SpecExample3;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class FirstFailSpec extends ObjectBehavior
{
function it_fails()
{
$this->getValue()->shouldReturn(2);
}
function it_should_never_get_called()
{
$this->getValue()->shouldReturn(1);
}
}
"""
And the class file "src/SkipOnFailure/SpecExample3/FirstFail.php" contains:
"""
<?php
namespace SkipOnFailure\SpecExample3;
class FirstFail
{
public function getValue()
{
return 1;
}
}
"""
When I run phpspec with the "stop-on-failure" option
Then 1 example should have been run
And the exit code should be 1

View File

@@ -1,125 +0,0 @@
Feature: Developer is told about pending specs
So that I remember to implement specs
As a Developer
I should be told about specs with missing bodies
Scenario: Empty spec causes pending result
Given the spec file "spec/Runner/PendingExample1/MarkdownSpec.php" contains:
"""
<?php
namespace spec\Runner\PendingExample1;
use PhpSpec\ObjectBehavior;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
}
}
"""
When I run phpspec using the "pretty" format
Then I should see:
"""
9 - converts plain text to html paragraphs
todo: write pending example
1 specs
1 examples (1 pending)
"""
Scenario: Spec with comments causes pending result
Given the spec file "spec/Runner/PendingExample2/MarkdownSpec.php" contains:
"""
<?php
namespace spec\Runner\PendingExample2;
use PhpSpec\ObjectBehavior;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
/**
multi-line doc - comment
*/
/*
multi-line comment
*/
// single-line comment
}
}
"""
When I run phpspec using the "pretty" format
Then I should see:
"""
9 - converts plain text to html paragraphs
todo: write pending example
1 specs
1 examples (1 pending)
"""
@issue492
Scenario: Comments with braces do not confuse the parser
Given the spec file "spec/Runner/PendingExample3/MarkdownSpec.php" contains:
"""
<?php
namespace spec\Runner\PendingExample3;
use PhpSpec\ObjectBehavior;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
pow(2,2);
// {
}
}
"""
When I run phpspec using the "pretty" format
Then I should see:
"""
1 examples (1 passed)
"""
@php-version @php5.4
Scenario: Spec defined in trait does not cause pending
Given the trait file "spec/Runner/PendingExample4/PartialSpecTrait.php" contains:
"""
<?php
namespace spec\Runner\PendingExample4;
trait PartialSpecTrait
{
function it_converts_plain_text_to_html_paragraphs()
{
pow(2,2);
}
}
"""
And the spec file "spec/Runner/PendingExample4/MarkdownSpec.php" contains:
"""
<?php
namespace spec\Runner\PendingExample4;
use PhpSpec\ObjectBehavior;
class MarkdownSpec extends ObjectBehavior
{
use PartialSpecTrait;
}
"""
When I run phpspec using the "pretty" format
Then I should see:
"""
1 examples (1 passed)
"""

View File

@@ -1,132 +0,0 @@
Feature: Developer runs the specs
As a Developer
I want to run the specs
In order to get feedback on a state of my application
Scenario: Running a spec with a class that doesn't exist
Given I have started describing the "Runner/SpecExample1/Markdown" class
When I run phpspec
Then I should see "class Runner\SpecExample1\Markdown does not exist"
Scenario: Reporting success when running a spec with correctly implemented class
Given the spec file "spec/Runner/SpecExample2/MarkdownSpec.php" contains:
"""
<?php
namespace spec\Runner\SpecExample2;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
}
"""
And the class file "src/Runner/SpecExample2/Markdown.php" contains:
"""
<?php
namespace Runner\SpecExample2;
class Markdown
{
public function toHtml($text)
{
return sprintf('<p>%s</p>', $text);
}
}
"""
When I run phpspec
Then the suite should pass
@issue214
Scenario: Letgo is executed after successful spec
Given the spec file "spec/Runner/SpecExample3/MarkdownSpec.php" contains:
"""
<?php
namespace spec\Runner\SpecExample3;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function letgo()
{
throw new \Exception('Letgo is called');
}
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
}
"""
And the class file "src/Runner/SpecExample3/Markdown.php" contains:
"""
<?php
namespace Runner\SpecExample3;
class Markdown
{
public function toHtml($text)
{
return sprintf('<p>%s</p>', $text);
}
}
"""
When I run phpspec
Then I should see "Letgo is called"
@issue214
Scenario: Letgo is executed after exception is thrown
Given the spec file "spec/Runner/SpecExample4/MarkdownSpec.php" contains:
"""
<?php
namespace spec\Runner\SpecExample4;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function letgo()
{
throw new \Exception('Letgo is called');
}
function it_converts_plain_text_to_html_paragraphs()
{
$this->toHtml('Hi, there')->shouldReturn('<p>Hi, there</p>');
}
}
"""
And the class file "src/Runner/SpecExample4/Markdown.php" contains:
"""
<?php
namespace Runner\SpecExample4;
class Markdown
{
public function toHtml($text)
{
throw new \Exception('Some exception');
}
}
"""
When I run phpspec
Then I should see "Letgo is called"

View File

@@ -1,31 +0,0 @@
Feature: Developer runs the specs with bootstrap option
As a Developer
I want to run the specs and specify bootstrap file
In order to get feedback on a state of my application
Scenario: Running a spec with --bootstrap option
Given the bootstrap file "bootstrap.php" contains:
"""
<?php
throw new \Exception('bootstrap file is loaded');
"""
When I run phpspec with option --bootstrap=bootstrap.php
Then I should see "bootstrap file is loaded"
Scenario: Running a spec with bootstrap option in config file
Given the bootstrap file "bootstrap.php" contains:
"""
<?php
throw new \Exception('bootstrap file is loaded');
"""
And the config file contains:
"""
bootstrap: bootstrap.php
"""
When I run phpspec
Then I should see "bootstrap file is loaded"
Scenario: Running a spec with --bootstrap option and bootstrap file is missing.
Given there is no file "missing.php"
When I run phpspec with option --bootstrap=missing.php
Then I should see "Bootstrap file 'missing.php' does not exist"

View File

@@ -1,42 +0,0 @@
Feature: Developer skips examples
As a Developer
I want to skip some examples I know won't pass
In order to sanitize my result output
Scenario: Skip a spec with and run it using the dot formatter
Given the spec file "spec/Runner/SpecExample/MarkdownSpec.php" contains:
"""
<?php
namespace spec\Runner\SpecExample;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use PhpSpec\Exception\Example\SkippingException;
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_table_to_html_table()
{
throw new SkippingException('subject to a php bug');
}
}
"""
And the class file "src/Runner/SpecExample/Markdown.php" contains:
"""
<?php
namespace Runner\SpecExample;
class Markdown
{
public function toHtml($text)
{
}
}
"""
When I run phpspec using the "dot" format
Then 1 example should have been skipped
But the suite should pass

View File

@@ -1,59 +0,0 @@
<?php
namespace integration\PhpSpec\Console\Prompter;
use PhpSpec\Console\Prompter\Dialog;
/**
* @requires function \Symfony\Component\Console\Helper\DialogHelper::askConfirmation
*/
class DialogTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \Symfony\Component\Console\Output\OutputInterface
*/
private $output;
/**
* @var \Symfony\Component\Console\Helper\DialogHelper
*/
private $dialogHelper;
/**
* @var \PhpSpec\Console\Prompter
*/
private $prompter;
protected function setUp()
{
$this->output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
$this->dialogHelper = $this->getMockBuilder('Symfony\Component\Console\Helper\DialogHelper')
->disableOriginalConstructor()->getMock();
$this->prompter = new Dialog($this->output, $this->dialogHelper);
}
/**
* @test
*/
function it_is_a_prompter()
{
$this->assertInstanceOf('PhpSpec\Console\Prompter', $this->prompter);
}
/**
* @test
*/
function it_can_ask_a_question_and_return_the_result()
{
$this->dialogHelper->expects($this->once())
->method('askConfirmation')
->with($this->identicalTo($this->output), 'Are you sure?', true)
->willReturn(true);
$result = $this->prompter->askConfirmation('Are you sure?');
$this->assertEquals(true, $result);
}
}

View File

@@ -1,108 +0,0 @@
<?php
namespace integration\PhpSpec\Console\Prompter;
use PhpSpec\Console\Prompter\Factory;
use Symfony\Component\Console\Helper\HelperSet;
class FactoryTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \Symfony\Component\Console\Input\InputInterface
*/
private $input;
/**
* @var \Symfony\Component\Console\Output\OutputInterface
*/
private $output;
/**
* @var int
*/
private $reportingLevel;
protected function setUp()
{
$this->reportingLevel = error_reporting();
error_reporting($this->reportingLevel & ~E_USER_DEPRECATED);
$this->input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
$this->output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
}
/**
* Symfony <2.5 case
*
* @requires function \Symfony\Component\Console\Helper\DialogHelper::askConfirmation
* @test
*/
function it_provides_a_dialog_prompter_when_only_dialoghelper_is_registered()
{
$dialogHelper = $this->getMock('Symfony\Component\Console\Helper\DialogHelper');
$helperSet = new HelperSet(array(
'dialog' => $dialogHelper
));
$factory = new Factory($this->input, $this->output, $helperSet);
$prompter = $factory->getPrompter();
$this->assertInstanceOf('PhpSpec\Console\Prompter\Dialog', $prompter);
$dialogHelper->expects($this->once())->method('askConfirmation');;
$prompter->askConfirmation('Are you sure?');
}
/**
* Symfony >=3.0 case
*
* @requires function \Symfony\Component\Console\Helper\QuestionHelper::ask
* @test
*/
function it_provides_a_question_prompter_when_only_questionhelper_is_registered()
{
$questionHelper = $this->getMock('Symfony\Component\Console\Helper\QuestionHelper');
$helperSet = new HelperSet(array(
'question' => $questionHelper
));
$factory = new Factory($this->input, $this->output, $helperSet);
$prompter = $factory->getPrompter();
$this->assertInstanceOf('PhpSpec\Console\Prompter\Question', $prompter);
$questionHelper->expects($this->once())->method('ask');
$prompter->askConfirmation('Are you sure?');
}
/**
* Symfony >=2.5 <3.0 case
*
* @requires function \Symfony\Component\Console\Helper\QuestionHelper::ask
* @requires function \Symfony\Component\Console\Helper\DialogHelper::askConfirmation
* @test
*/
function it_provides_a_question_prompter_when_both_prompters_are_registered()
{
$dialogHelper = $this->getMock('Symfony\Component\Console\Helper\DialogHelper');
$questionHelper = $this->getMock('Symfony\Component\Console\Helper\QuestionHelper');
$helperSet = new HelperSet(array(
'dialog' => $dialogHelper,
'question' => $questionHelper
));
$factory = new Factory($this->input, $this->output, $helperSet);
$prompter = $factory->getPrompter();
$this->assertInstanceOf('PhpSpec\Console\Prompter\Question', $prompter);
$questionHelper->expects($this->once())->method('ask');
$prompter->askConfirmation('Are you sure?');
}
protected function tearDown()
{
error_reporting($this->reportingLevel);
}
}

View File

@@ -1,69 +0,0 @@
<?php
namespace integration\PhpSpec\Console\Prompter;
use PhpSpec\Console\Prompter\Question;
use Symfony\Component\Console\Question\ConfirmationQuestion;
/**
* @requires function \Symfony\Component\Console\Helper\QuestionHelper::ask
*/
class QuestionTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \Symfony\Component\Console\Input\InputInterface
*/
private $input;
/**
* @var \Symfony\Component\Console\Output\OutputInterface
*/
private $output;
/**
* @var \Symfony\Component\Console\Helper\QuestionHelper
*/
private $questionHelper;
/**
* @var \PhpSpec\Console\Prompter
*/
private $prompter;
protected function setUp()
{
$this->input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
$this->output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
$this->questionHelper = $this->getMock('Symfony\Component\Console\Helper\QuestionHelper');
$this->prompter = new Question($this->input, $this->output, $this->questionHelper);
}
/**
* @test
*/
function it_is_a_prompter()
{
$this->assertInstanceOf('PhpSpec\Console\Prompter', $this->prompter);
}
/**
* @test
*/
function it_can_ask_a_question_and_return_the_result()
{
$this->questionHelper->expects($this->once())
->method('ask')
->with(
$this->identicalTo($this->input),
$this->identicalTo($this->output),
$this->equalTo(new ConfirmationQuestion('Are you sure?', true))
)
->willReturn(true);
$result = $this->prompter->askConfirmation('Are you sure?');
$this->assertEquals(true, $result);
}
}

View File

@@ -1 +0,0 @@
formatter.name: pretty

View File

@@ -1,7 +0,0 @@
<phpunit bootstrap="vendor/autoload.php">
<testsuites>
<testsuite>
<directory>integration</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@@ -1,120 +0,0 @@
<?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

@@ -1,79 +0,0 @@
<?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

@@ -1,82 +0,0 @@
<?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

@@ -1,38 +0,0 @@
<?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

@@ -1,120 +0,0 @@
<?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

@@ -1,46 +0,0 @@
<?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

@@ -1,98 +0,0 @@
<?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

@@ -1,51 +0,0 @@
<?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

@@ -1,19 +0,0 @@
<?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

@@ -1,183 +0,0 @@
<?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

@@ -1,35 +0,0 @@
<?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

@@ -1,58 +0,0 @@
<?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

@@ -1,77 +0,0 @@
<?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

@@ -1,66 +0,0 @@
<?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

@@ -1,45 +0,0 @@
<?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

@@ -1,48 +0,0 @@
<?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

@@ -1,28 +0,0 @@
<?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

@@ -1,25 +0,0 @@
<?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

@@ -1,173 +0,0 @@
<?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

@@ -1,21 +0,0 @@
<?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

@@ -1,23 +0,0 @@
<?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

@@ -1,28 +0,0 @@
<?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

@@ -1,33 +0,0 @@
<?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

@@ -1,34 +0,0 @@
<?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

@@ -1,34 +0,0 @@
<?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

@@ -1,28 +0,0 @@
<?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');
}
}

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