codeception 추가

- unit test 이전
This commit is contained in:
bnu 2015-04-10 17:00:57 +09:00
parent 6d093aed91
commit dd667fd578
32 changed files with 5462 additions and 0 deletions

View file

@ -6,7 +6,10 @@ php:
- 5.6
- hhvm
before_script:
- travis_retry composer self-update
- npm install -g grunt-cli
- npm install
- if [ $(phpenv version-name) != "5.3" ]; then composer install; fi
script:
- grunt lint
- if [ $(phpenv version-name) != "5.3" ]; then ./vendor/bin/codecept run; fi

18
codeception.yml Normal file
View file

@ -0,0 +1,18 @@
actor: Tester
paths:
tests: tests
log: tests/_output
data: tests/_data
helpers: tests/_support
settings:
bootstrap: _bootstrap.php
colors: true
memory_limit: 1024M
modules:
config:
Db:
dsn: ''
user: ''
password: ''
dump: tests/_data/dump.sql
error_level: "E_STRICTE_ALL & ~E_WARNING & ~E_STRICT & ~E_DEPRECATED & ~E_NOTICE"

17
composer.json Normal file
View file

@ -0,0 +1,17 @@
{
"name": "xpressengine/xe-core",
"license": "GNU LGPL",
"authors": [
{
"name": "NAVER",
"email": "developers@xpressengine.com"
}
],
"require": {
},
"require-dev": {
"codeception/codeception": "~2.0",
"codeception/verify": "0.2.*",
"codeception/specify": "0.4.*"
}
}

1741
composer.lock generated Normal file

File diff suppressed because it is too large Load diff

3
tests/_bootstrap.php Normal file
View file

@ -0,0 +1,3 @@
<?php
// This is global bootstrap for autoloading
if(!defined('_XE_PATH_')) define('_XE_PATH_', realpath(dirname(__FILE__).'/../').'/');

1
tests/_data/dump.sql Normal file
View file

@ -0,0 +1 @@
/* Replace this file with actual dump of your database */

View file

@ -0,0 +1,10 @@
<?php
namespace Codeception\Module;
// here you can define custom actions
// all public methods declared in helper class will be available in $I
class AcceptanceHelper extends \Codeception\Module
{
}

View file

@ -0,0 +1,10 @@
<?php
namespace Codeception\Module;
// here you can define custom actions
// all public methods declared in helper class will be available in $I
class FunctionalHelper extends \Codeception\Module
{
}

View file

@ -0,0 +1,10 @@
<?php
namespace Codeception\Module;
// here you can define custom actions
// all public methods declared in helper class will be available in $I
class UnitHelper extends \Codeception\Module
{
}

View file

@ -0,0 +1,8 @@
class_name: AcceptanceTester
modules:
enabled:
- PhpBrowser
- AcceptanceHelper
config:
PhpBrowser:
url: 'http://localhost/'

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
<?php
// Here you can initialize variables that will be available to your tests

View file

@ -0,0 +1,9 @@
# Codeception Test Suite Configuration
# suite for functional (integration) tests.
# emulate web requests and make application process them.
# Include one of framework modules (Symfony2, Yii2, Laravel4) to use it.
class_name: FunctionalTester
modules:
enabled: [Filesystem, FunctionalHelper]

View file

@ -0,0 +1,360 @@
<?php //[STAMP] d7bbcd1f0dd429da5e6566970c6feb56
// This class was automatically generated by build task
// You should not change it manually as it will be overwritten on next build
// @codingStandardsIgnoreFile
use Codeception\Module\Filesystem;
use Codeception\Module\FunctionalHelper;
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void expect($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method void haveFriend($name, $actorClass = null)
*
* @SuppressWarnings(PHPMD)
*/
class FunctionalTester extends \Codeception\Actor
{
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Enters a directory In local filesystem.
* Project root directory is used by default
*
* @param $path
* @see \Codeception\Module\Filesystem::amInPath()
*/
public function amInPath($path) {
return $this->scenario->runStep(new \Codeception\Step\Condition('amInPath', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Opens a file and stores it's content.
*
* Usage:
*
* ``` php
* <?php
* $I->openFile('composer.json');
* $I->seeInThisFile('codeception/codeception');
* ?>
* ```
*
* @param $filename
* @see \Codeception\Module\Filesystem::openFile()
*/
public function openFile($filename) {
return $this->scenario->runStep(new \Codeception\Step\Action('openFile', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Deletes a file
*
* ``` php
* <?php
* $I->deleteFile('composer.lock');
* ?>
* ```
*
* @param $filename
* @see \Codeception\Module\Filesystem::deleteFile()
*/
public function deleteFile($filename) {
return $this->scenario->runStep(new \Codeception\Step\Action('deleteFile', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Deletes directory with all subdirectories
*
* ``` php
* <?php
* $I->deleteDir('vendor');
* ?>
* ```
*
* @param $dirname
* @see \Codeception\Module\Filesystem::deleteDir()
*/
public function deleteDir($dirname) {
return $this->scenario->runStep(new \Codeception\Step\Action('deleteDir', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Copies directory with all contents
*
* ``` php
* <?php
* $I->copyDir('vendor','old_vendor');
* ?>
* ```
*
* @param $src
* @param $dst
* @see \Codeception\Module\Filesystem::copyDir()
*/
public function copyDir($src, $dst) {
return $this->scenario->runStep(new \Codeception\Step\Action('copyDir', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks If opened file has `text` in it.
*
* Usage:
*
* ``` php
* <?php
* $I->openFile('composer.json');
* $I->seeInThisFile('codeception/codeception');
* ?>
* ```
*
* @param $text
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Filesystem::seeInThisFile()
*/
public function canSeeInThisFile($text) {
return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeInThisFile', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks If opened file has `text` in it.
*
* Usage:
*
* ``` php
* <?php
* $I->openFile('composer.json');
* $I->seeInThisFile('codeception/codeception');
* ?>
* ```
*
* @param $text
* @see \Codeception\Module\Filesystem::seeInThisFile()
*/
public function seeInThisFile($text) {
return $this->scenario->runStep(new \Codeception\Step\Assertion('seeInThisFile', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks the strict matching of file contents.
* Unlike `seeInThisFile` will fail if file has something more than expected lines.
* Better to use with HEREDOC strings.
* Matching is done after removing "\r" chars from file content.
*
* ``` php
* <?php
* $I->openFile('process.pid');
* $I->seeFileContentsEqual('3192');
* ?>
* ```
*
* @param $text
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Filesystem::seeFileContentsEqual()
*/
public function canSeeFileContentsEqual($text) {
return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeFileContentsEqual', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks the strict matching of file contents.
* Unlike `seeInThisFile` will fail if file has something more than expected lines.
* Better to use with HEREDOC strings.
* Matching is done after removing "\r" chars from file content.
*
* ``` php
* <?php
* $I->openFile('process.pid');
* $I->seeFileContentsEqual('3192');
* ?>
* ```
*
* @param $text
* @see \Codeception\Module\Filesystem::seeFileContentsEqual()
*/
public function seeFileContentsEqual($text) {
return $this->scenario->runStep(new \Codeception\Step\Assertion('seeFileContentsEqual', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks If opened file doesn't contain `text` in it
*
* ``` php
* <?php
* $I->openFile('composer.json');
* $I->dontSeeInThisFile('codeception/codeception');
* ?>
* ```
*
* @param $text
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Filesystem::dontSeeInThisFile()
*/
public function cantSeeInThisFile($text) {
return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInThisFile', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks If opened file doesn't contain `text` in it
*
* ``` php
* <?php
* $I->openFile('composer.json');
* $I->dontSeeInThisFile('codeception/codeception');
* ?>
* ```
*
* @param $text
* @see \Codeception\Module\Filesystem::dontSeeInThisFile()
*/
public function dontSeeInThisFile($text) {
return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeInThisFile', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Deletes a file
* @see \Codeception\Module\Filesystem::deleteThisFile()
*/
public function deleteThisFile() {
return $this->scenario->runStep(new \Codeception\Step\Action('deleteThisFile', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks if file exists in path.
* Opens a file when it's exists
*
* ``` php
* <?php
* $I->seeFileFound('UserModel.php','app/models');
* ?>
* ```
*
* @param $filename
* @param string $path
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Filesystem::seeFileFound()
*/
public function canSeeFileFound($filename, $path = null) {
return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeFileFound', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks if file exists in path.
* Opens a file when it's exists
*
* ``` php
* <?php
* $I->seeFileFound('UserModel.php','app/models');
* ?>
* ```
*
* @param $filename
* @param string $path
* @see \Codeception\Module\Filesystem::seeFileFound()
*/
public function seeFileFound($filename, $path = null) {
return $this->scenario->runStep(new \Codeception\Step\Assertion('seeFileFound', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks if file does not exists in path
*
* @param $filename
* @param string $path
* Conditional Assertion: Test won't be stopped on fail
* @see \Codeception\Module\Filesystem::dontSeeFileFound()
*/
public function cantSeeFileFound($filename, $path = null) {
return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeFileFound', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks if file does not exists in path
*
* @param $filename
* @param string $path
* @see \Codeception\Module\Filesystem::dontSeeFileFound()
*/
public function dontSeeFileFound($filename, $path = null) {
return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeFileFound', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Erases directory contents
*
* ``` php
* <?php
* $I->cleanDir('logs');
* ?>
* ```
*
* @param $dirname
* @see \Codeception\Module\Filesystem::cleanDir()
*/
public function cleanDir($dirname) {
return $this->scenario->runStep(new \Codeception\Step\Action('cleanDir', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Saves contents to file
*
* @param $filename
* @param $contents
* @see \Codeception\Module\Filesystem::writeToFile()
*/
public function writeToFile($filename, $contents) {
return $this->scenario->runStep(new \Codeception\Step\Action('writeToFile', func_get_args()));
}
}

View file

@ -0,0 +1,2 @@
<?php
// Here you can initialize variables that will be available to your tests

6
tests/unit.suite.yml Normal file
View file

@ -0,0 +1,6 @@
# Codeception Test Suite Configuration
# suite for unit (internal) tests.
class_name: UnitTester
modules:
enabled: [Asserts, UnitHelper]

View file

@ -0,0 +1,55 @@
<?php
require _XE_PATH_.'/config/func.inc.php';
class FuncIncTest extends \Codeception\TestCase\Test
{
static public function xssProvider()
{
return array(
// remove iframe
array(
'<div class="frame"><iframe src="path/to/file.html"></iframe><p><a href="#iframe">IFrame</a></p></div>',
'<div class="frame">&lt;iframe src="path/to/file.html">&lt;/iframe><p><a href="#iframe">IFrame</a></p></div>'
),
// expression
array(
'<div class="dummy" style="xss:expr/*XSS*/ession(alert(\'XSS\'))">',
'<div class="dummy">'
),
// no quotes and no semicolon - http://ha.ckers.org/xss.html
array(
'<img src=javascript:alert(\'xss\')>',
'<img>'
),
// embedded encoded tab to break up XSS - http://ha.ckers.org/xss.html
array(
'<IMG SRC="jav&#x09;ascript:alert(\'XSS\');">',
'<img>'
),
// issue 178
array(
"<img src=\"invalid\"\nonerror=\"alert(1)\" />",
'<img src="invalid" />'
),
// issue 534
array(
'<img src=\'as"df dummy=\'"1234\'" 4321\' asdf/*/>*/" onerror="console.log(\'Yet another XSS\')">',
'<img src="as&quot;df dummy=" />*/" onerror="console.log(\'Yet another XSS\')">'
),
// issue 602
array(
'<img alt="test" src="(http://static.naver.com/www/u/2010/0611/nmms_215646753.gif" onload="eval(String.fromCharCode(105,61,49,48,48,59,119,104,105,108,101, 40,105,62,48,41,97,108,101,114,116,40,40,105,45,45,41,43,39,48264,47564,32, 45908,32,53364,47533,54616,49464,50836,39,41,59));">',
'<img alt="test" src="(http://static.naver.com/www/u/2010/0611/nmms_215646753.gif">'
)
);
}
/**
* @dataProvider xssProvider
*/
public function testXSS($source, $expected)
{
$result = removeHackTag($source);
$this->assertEquals($result, $expected);
}
}

300
tests/unit/UnitTester.php Normal file
View file

@ -0,0 +1,300 @@
<?php //[STAMP] 82bc9161e8772dbad0b5d616567eaa2d
// This class was automatically generated by build task
// You should not change it manually as it will be overwritten on next build
// @codingStandardsIgnoreFile
use Codeception\Module\Asserts;
use Codeception\Module\UnitHelper;
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void expect($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method void haveFriend($name, $actorClass = null)
*
* @SuppressWarnings(PHPMD)
*/
class UnitTester extends \Codeception\Actor
{
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that two variables are equal.
*
* @param $expected
* @param $actual
* @param string $message
*
* @return mixed
* @see \Codeception\Module\Asserts::assertEquals()
*/
public function assertEquals($expected, $actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertEquals', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that two variables are not equal
*
* @param $expected
* @param $actual
* @param string $message
* @see \Codeception\Module\Asserts::assertNotEquals()
*/
public function assertNotEquals($expected, $actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertNotEquals', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that two variables are same
*
* @param $expected
* @param $actual
* @param string $message
*
* @return mixed
* @see \Codeception\Module\Asserts::assertSame()
*/
public function assertSame($expected, $actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertSame', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that two variables are not same
*
* @param $expected
* @param $actual
* @param string $message
* @see \Codeception\Module\Asserts::assertNotSame()
*/
public function assertNotSame($expected, $actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertNotSame', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that expected is greater than actual
*
* @param $expected
* @param $actual
* @param string $message
* @see \Codeception\Module\Asserts::assertGreaterThan()
*/
public function assertGreaterThan($expected, $actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertGreaterThan', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* @deprecated
* @see \Codeception\Module\Asserts::assertGreaterThen()
*/
public function assertGreaterThen($expected, $actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertGreaterThen', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that expected is greater or equal than actual
*
* @param $expected
* @param $actual
* @param string $message
* @see \Codeception\Module\Asserts::assertGreaterThanOrEqual()
*/
public function assertGreaterThanOrEqual($expected, $actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertGreaterThanOrEqual', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* @deprecated
* @see \Codeception\Module\Asserts::assertGreaterThenOrEqual()
*/
public function assertGreaterThenOrEqual($expected, $actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertGreaterThenOrEqual', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that expected is less than actual
*
* @param $expected
* @param $actual
* @param string $message
* @see \Codeception\Module\Asserts::assertLessThan()
*/
public function assertLessThan($expected, $actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertLessThan', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that expected is less or equal than actual
*
* @param $expected
* @param $actual
* @param string $message
* @see \Codeception\Module\Asserts::assertLessThanOrEqual()
*/
public function assertLessThanOrEqual($expected, $actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertLessThanOrEqual', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that haystack contains needle
*
* @param $needle
* @param $haystack
* @param string $message
* @see \Codeception\Module\Asserts::assertContains()
*/
public function assertContains($needle, $haystack, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertContains', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that haystack doesn't contain needle.
*
* @param $needle
* @param $haystack
* @param string $message
* @see \Codeception\Module\Asserts::assertNotContains()
*/
public function assertNotContains($needle, $haystack, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertNotContains', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that variable is empty.
*
* @param $actual
* @param string $message
* @see \Codeception\Module\Asserts::assertEmpty()
*/
public function assertEmpty($actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertEmpty', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that variable is not empty.
*
* @param $actual
* @param string $message
* @see \Codeception\Module\Asserts::assertNotEmpty()
*/
public function assertNotEmpty($actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertNotEmpty', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that variable is NULL
*
* @param $actual
* @param string $message
* @see \Codeception\Module\Asserts::assertNull()
*/
public function assertNull($actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertNull', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that variable is not NULL
*
* @param $actual
* @param string $message
* @see \Codeception\Module\Asserts::assertNotNull()
*/
public function assertNotNull($actual, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertNotNull', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that condition is positive.
*
* @param $condition
* @param string $message
* @see \Codeception\Module\Asserts::assertTrue()
*/
public function assertTrue($condition, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertTrue', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Checks that condition is negative.
*
* @param $condition
* @param string $message
* @see \Codeception\Module\Asserts::assertFalse()
*/
public function assertFalse($condition, $message = null) {
return $this->scenario->runStep(new \Codeception\Step\Action('assertFalse', func_get_args()));
}
/**
* [!] Method is generated. Documentation taken from corresponding module.
*
* Fails the test with message.
*
* @param $message
* @see \Codeception\Module\Asserts::fail()
*/
public function fail($message) {
return $this->scenario->runStep(new \Codeception\Step\Action('fail', func_get_args()));
}
}

30
tests/unit/_bootstrap.php Normal file
View file

@ -0,0 +1,30 @@
<?php
use Codeception\Util\Debug;
if(!defined('__XE__')) define('__XE__', TRUE);
if(!defined('_XE_PATH_')) define('_XE_PATH_', realpath(dirname(__FILE__).'/../').'/');
$_SERVER['SCRIPT_NAME'] = '/xe/index.php';
error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED ^ E_WARNING ^ E_STRICT);
function _log() {
$args = func_get_args();
$bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT, 2);
if(is_array($bt))
{
$bt_debug_print = array_shift($bt);
$bt_called_function = array_shift($bt);
}
$file_name = str_replace(_XE_PATH_, '', $bt_debug_print['file']);
$line_num = $bt_debug_print['line'];
$function = $bt_called_function['class'] . $bt_called_function['type'] . $bt_called_function['function'];
$print = sprintf("%s() [%s:%d]", $function, $file_name, $line_num);
Debug::debug("\n" . $print);
foreach($args as $arg) {
Debug::debug('(' . gettype($arg) . ') ' . var_export($arg, true));
}
}

View file

@ -0,0 +1,90 @@
<?php
require_once _XE_PATH_.'classes/context/Context.class.php';
require_once _XE_PATH_.'classes/handler/Handler.class.php';
require_once _XE_PATH_.'classes/frontendfile/FrontEndFileHandler.class.php';
class ContextTest extends \Codeception\TestCase\Test
{
/**
* @var \UnitTester
*/
protected $tester;
protected function _before()
{
}
protected function _after()
{
}
public function testGetInstance()
{
$this->assertInstanceOf('Context', Context::getInstance());
$this->assertSame(Context::getInstance(), Context::getInstance());
}
public function testSetGetVars()
{
$this->assertEquals(Context::get('var1'), null);
context::set('var1', 'val1');
$this->assertEquals(Context::get('var1'), 'val1');
Context::set('var2', 'val2');
$this->assertSame(Context::get('var2'), 'val2');
Context::set('var3', 'val3');
$data = new stdClass();
$data->var1 = 'val1';
$data->var2 = 'val2';
$this->assertEquals(Context::gets('var1','var2'), $data);
$data->var3 = 'val3';
$this->assertEquals(Context::getAll(), $data);
}
public function testAddGetBodyClass()
{
$this->assertEquals(Context::getBodyClass(), '');
Context::addBodyClass('red');
$this->assertEquals(Context::getBodyClass(), ' class="red"');
Context::addBodyClass('green');
$this->assertEquals(Context::getBodyClass(), ' class="red green"');
Context::addBodyClass('blue');
$this->assertEquals(Context::getBodyClass(), ' class="red green blue"');
// remove duplicated class
Context::addBodyClass('red');
$this->assertEquals(Context::getBodyClass(), ' class="red green blue"');
}
public function testRequsetResponseMethod()
{
$this->assertEquals(Context::getRequestMethod(), 'GET');
$_SERVER['REQUEST_METHOD'] = 'POST';
Context::setRequestMethod();
$this->assertEquals(Context::getRequestMethod(), 'POST');
$GLOBALS['HTTP_RAW_POST_DATA'] = 'abcde';
Context::setRequestMethod();
$this->assertEquals(Context::getRequestMethod(), 'XMLRPC');
$_SERVER['CONTENT_TYPE'] = 'application/json';
Context::setRequestMethod();
$this->assertEquals(Context::getRequestMethod(), 'JSON');
Context::setRequestMethod('POST');
$this->assertEquals(Context::getRequestMethod(), 'POST');
$this->assertEquals(Context::getResponseMethod(), 'HTML');
Context::setRequestMethod('JSON');
$this->assertEquals(Context::getResponseMethod(), 'JSON');
Context::setResponseMethod('WRONG_TYPE');
$this->assertEquals(Context::getResponseMethod(), 'HTML');
Context::setResponseMethod('XMLRPC');
$this->assertEquals(Context::getResponseMethod(), 'XMLRPC');
Context::setResponseMethod('HTML');
$this->assertEquals(Context::getResponseMethod(), 'HTML');
}
}

View file

@ -0,0 +1,44 @@
<?php
require_once _XE_PATH_.'classes/file/FileHandler.class.php';
class FileHandlerTest extends \Codeception\TestCase\Test
{
/**
* @var \UnitTester
*/
protected $tester;
protected function _before()
{
}
protected function _after()
{
}
// tests
public function testFileSize()
{
// file size
$this->assertEquals(FileHandler::filesize(0), '0Byte');
$this->assertEquals(FileHandler::filesize(1), '1Byte');
$this->assertEquals(FileHandler::filesize(386), '386Bytes');
$this->assertEquals(FileHandler::filesize(1023), '1023Bytes');
$this->assertEquals(FileHandler::filesize(1024), '1.0KB');
$this->assertEquals(FileHandler::filesize(2480), '2.4KB');
$this->assertEquals(FileHandler::filesize(1024*1024-1), '1024.0KB');
$this->assertEquals(FileHandler::filesize(1024*1024), '1.00MB');
$this->assertEquals(FileHandler::filesize(3*1024*1024+210*1024), '3.21MB');
// return bytes
$this->assertEquals(FileHandler::returnBytes('0B'), 0);
$this->assertEquals(FileHandler::returnBytes('1024B'), 1024);
$this->assertEquals(FileHandler::returnBytes('1K'), 1024);
$this->assertEquals(FileHandler::returnBytes('102.48K'), round(1024*102.48));
$this->assertEquals(FileHandler::returnBytes('1M'), 1024*1024);
$this->assertEquals(FileHandler::returnBytes('1.12M'), round(1024*1024*1.12));
$this->assertEquals(FileHandler::returnBytes('1023.99M'), round(1024*1024*1023.99));
$this->assertEquals(FileHandler::returnBytes('1G'), 1024*1024*1024);
$this->assertEquals(FileHandler::returnBytes('12.02G'), round(1024*1024*1024*12.02));
}
}

View file

@ -0,0 +1,158 @@
<?php
require_once _XE_PATH_.'classes/frontendfile/FrontEndFileHandler.class.php';
class FrontEndFileHandlerTest extends \Codeception\TestCase\Test
{
use \Codeception\Specify;
private function _filemtime($file)
{
return '?' . date('YmdHis', filemtime(_XE_PATH_ . $file));
}
public function testFrontEndFileHandler()
{
$handler = new FrontEndFileHandler();
$this->specify("js(head)", function() {
$handler = new FrontEndFileHandler();
$handler->loadFile(array('./common/js/jquery.js'));
$handler->loadFile(array('./common/js/js_app.js', 'head'));
$handler->loadFile(array('./common/js/common.js', 'body'));
$handler->loadFile(array('./common/js/common.js', 'head'));
$handler->loadFile(array('./common/js/xml_js_filter.js', 'body'));
$expected[] = array('file' => '/xe/common/js/jquery.js' . $this->_filemtime('common/js/jquery.js'), 'targetie' => null);
$expected[] = array('file' => '/xe/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => null);
$expected[] = array('file' => '/xe/common/js/common.js' . $this->_filemtime('common/js/common.js'), 'targetie' => null);
$this->assertEquals($handler->getJsFileList(), $expected);
});
$this->specify("js(body)", function() {
$handler = new FrontEndFileHandler();
$handler->loadFile(array('./common/js/jquery.js', 'body'));
$handler->loadFile(array('./common/js/xml_js_filter.js', 'head'));
$expected[] = array('file' => '/xe/common/js/jquery.js' . $this->_filemtime('common/js/jquery.js'), 'targetie' => null);
$this->assertEquals($handler->getJsFileList('body'), $expected);
});
$this->specify("css", function() {
$handler = new FrontEndFileHandler();
$handler->loadFile(array('./common/css/xe.css'));
$handler->loadFile(array('./common/css/mobile.css'));
$expected[] = array('file' => '/xe/common/css/xe.css' . $this->_filemtime('common/css/xe.css'), 'media' => 'all', 'targetie' => null);
$expected[] = array('file' => '/xe/common/css/mobile.css' . $this->_filemtime('common/css/mobile.css'), 'media' => 'all', 'targetie' => null);
$this->assertEquals($handler->getCssFileList(), $expected);
});
$this->specify("order (duplicate)", function() {
$handler = new FrontEndFileHandler();
$handler->loadFile(array('./common/js/jquery.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/js_app.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/common.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/xml_handler.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/xml_js_filter.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/jquery.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/js_app.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/common.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/xml_handler.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/xml_js_filter.js', 'head', '', -100000));
$expected[] = array('file' => '/xe/common/js/jquery.js' . $this->_filemtime('common/js/jquery.js'), 'targetie' => null);
$expected[] = array('file' => '/xe/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => null);
$expected[] = array('file' => '/xe/common/js/common.js' . $this->_filemtime('common/js/common.js'), 'targetie' => null);
$expected[] = array('file' => '/xe/common/js/xml_handler.js' . $this->_filemtime('common/js/xml_handler.js'), 'targetie' => null);
$expected[] = array('file' => '/xe/common/js/xml_js_filter.js' . $this->_filemtime('common/js/xml_js_filter.js'), 'targetie' => null);
$this->assertEquals($handler->getJsFileList(), $expected);
});
$this->specify("order (redefine)", function() {
$handler = new FrontEndFileHandler();
$handler->loadFile(array('./common/js/xml_handler.js', 'head', '', 1));
$handler->loadFile(array('./common/js/jquery.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/js_app.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/common.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/xml_js_filter.js', 'head', '', -100000));
$expected[] = array('file' => '/xe/common/js/jquery.js' . $this->_filemtime('common/js/jquery.js'), 'targetie' => null);
$expected[] = array('file' => '/xe/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => null);
$expected[] = array('file' => '/xe/common/js/common.js' . $this->_filemtime('common/js/common.js'), 'targetie' => null);
$expected[] = array('file' => '/xe/common/js/xml_js_filter.js' . $this->_filemtime('common/js/xml_js_filter.js'), 'targetie' => null);
$expected[] = array('file' => '/xe/common/js/xml_handler.js' . $this->_filemtime('common/js/xml_handler.js'), 'targetie' => null);
$this->assertEquals($handler->getJsFileList(), $expected);
});
$this->specify("unload", function() {
$handler = new FrontEndFileHandler();
$handler->loadFile(array('./common/js/jquery.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/js_app.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/common.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/xml_handler.js', 'head', '', -100000));
$handler->loadFile(array('./common/js/xml_js_filter.js', 'head', '', -100000));
$handler->unloadFile('./common/js/jquery.js', '', 'all');
$expected[] = array('file' => '/xe/common/js/js_app.js' . $this->_filemtime('common/js/js_app.js'), 'targetie' => null);
$expected[] = array('file' => '/xe/common/js/common.js' . $this->_filemtime('common/js/common.js'), 'targetie' => null);
$expected[] = array('file' => '/xe/common/js/xml_handler.js' . $this->_filemtime('common/js/xml_handler.js'), 'targetie' => null);
$expected[] = array('file' => '/xe/common/js/xml_js_filter.js' . $this->_filemtime('common/js/xml_js_filter.js'), 'targetie' => null);
$this->assertEquals($handler->getJsFileList(), $expected);
});
$this->specify("target IE(js)", function() {
$handler = new FrontEndFileHandler();
$handler->loadFile(array('./common/js/jquery.js', 'head', 'ie6'));
$handler->loadFile(array('./common/js/jquery.js', 'head', 'ie7'));
$handler->loadFile(array('./common/js/jquery.js', 'head', 'ie8'));
$expected[] = array('file' => '/xe/common/js/jquery.js' . $this->_filemtime('common/js/jquery.js'), 'targetie' => 'ie6');
$expected[] = array('file' => '/xe/common/js/jquery.js' . $this->_filemtime('common/js/jquery.js'), 'targetie' => 'ie7');
$expected[] = array('file' => '/xe/common/js/jquery.js' . $this->_filemtime('common/js/jquery.js'), 'targetie' => 'ie8');
$this->assertEquals($handler->getJsFileList(), $expected);
});
$this->specify("target IE(css)", function() {
$handler = new FrontEndFileHandler();
$handler->loadFile(array('./common/css/common.css', null, 'ie6'));
$handler->loadFile(array('./common/css/common.css', null, 'ie7'));
$handler->loadFile(array('./common/css/common.css', null, 'ie8'));
$expected[] = array('file' => '/xe/common/css/common.css', 'media'=>'all', 'targetie' => 'ie6');
$expected[] = array('file' => '/xe/common/css/common.css','media'=>'all', 'targetie' => 'ie7');
$expected[] = array('file' => '/xe/common/css/common.css', 'media'=>'all', 'targetie' => 'ie8');
$this->assertEquals($handler->getCssFileList(), $expected);
});
$this->specify("media", function() {
$handler = new FrontEndFileHandler();
$handler->loadFile(array('./common/css/common.css', 'all'));
$handler->loadFile(array('./common/css/common.css', 'screen'));
$handler->loadFile(array('./common/css/common.css', 'handled'));
$expected[] = array('file' => '/xe/common/css/common.css', 'media'=>'all', 'targetie' => null);
$expected[] = array('file' => '/xe/common/css/common.css','media'=>'screen', 'targetie' => null);
$expected[] = array('file' => '/xe/common/css/common.css', 'media'=>'handled', 'targetie' => null);
$this->assertEquals($handler->getCssFileList(), $expected);
});
$this->specify("external file", function() {
$handler = new FrontEndFileHandler();
$handler->loadFile(array('http://external.host/css/style1.css'));
$handler->loadFile(array('https://external.host/css/style2.css'));
$expected[] = array('file' => 'http://external.host/css/style1.css', 'media'=>'all', 'targetie' => null);
$expected[] = array('file' => 'https://external.host/css/style2.css', 'media'=>'all', 'targetie' => null);
$this->assertEquals($handler->getCssFileList(), $expected);
});
$this->specify("external file", function() {
$handler = new FrontEndFileHandler();
$handler->loadFile(array('//external.host/css/style.css'));
$expected[] = array('file' => '//external.host/css/style.css', 'media'=>'all', 'targetie' => null);
$this->assertEquals($handler->getCssFileList(), $expected);
});
}
}

View file

@ -0,0 +1,121 @@
<?php
require_once _XE_PATH_.'/classes/security/Security.class.php';
class SecurityTest extends \Codeception\TestCase\Test
{
protected function setUp()
{
/**
* Setup mock data
**/
// string
Context::set('content1', '<strong>Hello, world</strong>');
Context::set('content2', 'Wow, >_< !');
// object
$args = new stdClass;
$args->prop1 = 'Normal string';
$args->prop2 = 'He said, "Very nice!"';
$args->prop3 = '<strong>Strong</strong> Baby';
Context::set('object1', $args);
// array
$arr = array();
$arr[] = '<span class="first">F</span>irst';
$arr[] = '<u>S</u>econd';
$arr[] = '<b>T</b>hird';
Context::set('array1', $arr);
// associative array
$aarr = array();
$aarr['elem1'] = 'One <ins>1</ins>';
$aarr['elem2'] = 'Two <del>2</del>';
$aarr['elem3'] = 'Three <addr>3</addr>';
Context::set('array2', $aarr);
}
public function testEncodeHTML_DefaultContext()
{
$security = new Security();
// normal string - one
$this->setUp();
$this->assertEquals('<strong>Hello, world</strong>', Context::get('content1'));
$security->encodeHTML('content1');
$this->assertEquals('&lt;strong&gt;Hello, world&lt;/strong&gt;', Context::get('content1'));
// normal string - two
$this->setUp();
$this->assertEquals('<strong>Hello, world</strong>', Context::get('content1'));
$this->assertEquals('Wow, >_< !', Context::get('content2'));
$security->encodeHTML('content1','content2');
$this->assertEquals('&lt;strong&gt;Hello, world&lt;/strong&gt;', Context::get('content1'));
$this->assertEquals('Wow, &gt;_&lt; !', Context::get('content2'));
// array
$this->assertEquals(Context::get('array1'), array('<span class="first">F</span>irst','<u>S</u>econd','<b>T</b>hird'));
$security->encodeHTML('array1'); // should ignore this
$this->assertEquals(Context::get('array1'), array('<span class="first">F</span>irst','<u>S</u>econd','<b>T</b>hird'));
$security->encodeHTML('array1.0'); // affect only first element
$this->assertEquals(Context::get('array1'), array('&lt;span class=&quot;first&quot;&gt;F&lt;/span&gt;irst','<u>S</u>econd','<b>T</b>hird'));
$security->encodeHTML('array1.2'); // affects only third element
$this->assertEquals(Context::get('array1'), array('&lt;span class=&quot;first&quot;&gt;F&lt;/span&gt;irst','<u>S</u>econd','&lt;b&gt;T&lt;/b&gt;hird'));
$this->setUp(); // reset;
$this->assertEquals(Context::get('array1'), array('<span class="first">F</span>irst','<u>S</u>econd','<b>T</b>hird'));
$security->encodeHTML('array1.'); // affects all items
$this->assertEquals(Context::get('array1'), array('&lt;span class=&quot;first&quot;&gt;F&lt;/span&gt;irst','&lt;u&gt;S&lt;/u&gt;econd','&lt;b&gt;T&lt;/b&gt;hird'));
// associated array
$this->assertEquals(Context::get('array2'), array('elem1'=>'One <ins>1</ins>','elem2'=>'Two <del>2</del>','elem3'=>'Three <addr>3</addr>'));
$security->encodeHTML('array2'); // should ignore this
$this->assertEquals(Context::get('array2'), array('elem1'=>'One <ins>1</ins>','elem2'=>'Two <del>2</del>','elem3'=>'Three <addr>3</addr>'));
$security->encodeHTML('array2.0'); // should ignore this
$this->assertEquals(Context::get('array2'), array('elem1'=>'One <ins>1</ins>','elem2'=>'Two <del>2</del>','elem3'=>'Three <addr>3</addr>'));
$security->encodeHTML('array2.elem2'); // affects only 'elem2'
$this->assertEquals(Context::get('array2'), array('elem1'=>'One <ins>1</ins>','elem2'=>'Two &lt;del&gt;2&lt;/del&gt;','elem3'=>'Three <addr>3</addr>'));
$this->setUp(); // reset;
$this->assertEquals(Context::get('array2'), array('elem1'=>'One <ins>1</ins>','elem2'=>'Two <del>2</del>','elem3'=>'Three <addr>3</addr>'));
$security->encodeHTML('array2.'); // affects all items
$this->assertEquals(Context::get('array2'), array('elem1'=>'One &lt;ins&gt;1&lt;/ins&gt;','elem2'=>'Two &lt;del&gt;2&lt;/del&gt;','elem3'=>'Three &lt;addr&gt;3&lt;/addr&gt;'));
// object
$obj = new stdClass;
$obj->prop1 = 'Normal string';
$obj->prop2 = 'He said, "Very nice!"';
$obj->prop3 = '<strong>Strong</strong> Baby';
$this->assertEquals(Context::get('object1'), $obj);
$security->encodeHTML('object1'); // should ignore this
$this->assertEquals(Context::get('object1'), $obj);
$security->encodeHTML('object1.0'); // should ignore this
$this->assertEquals(Context::get('object1'), $obj);
$security->encodeHTML('object1.prop1'); // affects only 'prop1' property - no changes
$this->assertEquals(Context::get('object1'), $obj);
$security->encodeHTML('object1.prop3'); // affects only 'prop3' property
$obj->prop3 = '&lt;strong&gt;Strong&lt;/strong&gt; Baby';
$this->assertEquals(Context::get('object1'), $obj);
$this->setUp(); // reset
$obj->prop3 = '<strong>Strong</strong> Baby';
$this->assertEquals(Context::get('object1'), $obj);
$security->encodeHTML('object1.'); // affects all properties
$obj->prop2 = 'He said, &quot;Very nice!&quot;';
$obj->prop3 = '&lt;strong&gt;Strong&lt;/strong&gt; Baby';
$this->assertEquals(Context::get('object1'), $obj);
}
public function testEncodeHTML_CustomContext()
{
$array = array('Hello', 'World', '<b>Bold</b> is not bald');
// array with no nested objects or arrays
$security = new Security($array);
$returned = $security->encodeHTML('.');
$this->assertEquals($returned, array('Hello', 'World', '&lt;b&gt;Bold&lt;/b&gt; is not bald'));
// associative array
$array = array('first'=>'Hello', 'second'=>'World', '3rd'=>'<b>Bold</b> is not bald');
$security = new Security($array);
$returned = $security->encodeHTML('first','3rd');
$this->assertEquals($returned, array('first'=>'Hello', 'second'=>'World', '3rd'=>'&lt;b&gt;Bold&lt;/b&gt; is not bald'));
}
}

View file

@ -0,0 +1,282 @@
<?php
require_once _XE_PATH_.'classes/file/FileHandler.class.php';
require_once _XE_PATH_.'classes/template/TemplateHandler.class.php';
$_SERVER['SCRIPT_NAME'] = '/xe/tests/unit/classes/template/index.php';
class TemplateHandlerTest extends \Codeception\TestCase\Test
{
var $prefix = '<?php if(!defined("__XE__"))exit;';
static public function provider()
{
return array(
// pipe cond
array(
'<a href="#" class="active"|cond="$cond > 10">Link</a>',
'?><a href="#"<?php if($__Context->cond > 10){ ?> class="active"<?php } ?>>Link</a>'
),
// cond
array(
'<a href="#">Link1</a><a href="#cond"><span cond="$cond">say, hello</span></a>',
'?><a href="#">Link1</a><a href="#cond"><?php if($__Context->cond){ ?><span>say, hello</span><?php } ?></a>'
),
// cond
array(
'<a href="#">Link1</a><a href="#cond" cond="$v==$k">Link2</a>',
'?><a href="#">Link1</a><?php if($__Context->v==$__Context->k){ ?><a href="#cond">Link2</a><?php } ?>'
),
// for loop
array(
'<ul><li loop="$i=0;$i<$len;$i++" class="sample"><a>Link</a></li></ul>',
'?><ul><?php for($__Context->i=0;$__Context->i<$__Context->len;$__Context->i++){ ?><li class="sample"><a>Link</a></li><?php } ?></ul>'
),
// foreach loop
array(
'<ul><li loop="$arr=>$key,$val" class="sample"><a>Link</a><ul><li loop="$arr2=>$key2,$val2"></li></ul></li></ul>',
'?><ul><?php if($__Context->arr&&count($__Context->arr))foreach($__Context->arr as $__Context->key=>$__Context->val){ ?><li class="sample"><a>Link</a><ul><?php if($__Context->arr2&&count($__Context->arr2))foreach($__Context->arr2 as $__Context->key2=>$__Context->val2){ ?><li></li><?php } ?></ul></li><?php } ?></ul>'
),
// while loop
array(
'<ul><li loop="$item=get_loop_item()" class="sample"><a>Link</a></li></ul>',
'?><ul><?php while($__Context->item=get_loop_item()){ ?><li class="sample"><a>Link</a></li><?php } ?></ul>'
),
// <!--@if--> ~ <!--@end-->
array(
'<a>Link</a><!--@if($cond)--><strong>Hello, world</strong><!--@end--> <dummy />',
'?><a>Link</a><?php if($__Context->cond){ ?><strong>Hello, world</strong><?php } ?> <dummy />'
),
// <!--@if--> ~ <!--@endif-->
array(
'<a>Link</a><!--@if($cond)--><strong>Hello, {$world}</strong><!--@endif--><dummy />',
'?><a>Link</a><?php if($__Context->cond){ ?><strong>Hello, <?php echo $__Context->world ?></strong><?php } ?><dummy />'
),
// <!--@if--> ~ <!--@else--> ~ <!--@endif-->
array(
'<a>Link</a><!--@if($cond)--><strong>Hello, world</strong><!--@else--><em>Wow</em><!--@endif--><dummy />',
'?><a>Link</a><?php if($__Context->cond){ ?><strong>Hello, world</strong><?php }else{ ?><em>Wow</em><?php } ?><dummy />'
),
// <!--@if--> ~ <!--@elseif--> ~ <!--@else--> ~ <!--@endif-->
array(
'<a>Link</a><!--@if($cond)--><strong>Hello, world</strong><!--@elseif($cond2)--><u>HaHa</u><!--@else--><em>Wow</em><!--@endif--><dummy />',
'?><a>Link</a><?php if($__Context->cond){ ?><strong>Hello, world</strong><?php }elseif($__Context->cond2){ ?><u>HaHa</u><?php }else{ ?><em>Wow</em><?php } ?><dummy />'
),
// <!--@for--> ~ <!--@endfor-->
array(
'<!--@for($i=0;$i<$len;$i++)--><li>Repeat this</li><!--@endfor-->',
PHP_EOL.'for($__Context->i=0;$__Context->i<$__Context->len;$__Context->i++){ ?><li>Repeat this</li><?php } ?>'
),
// <!--@foreach--> ~ <!--@endforeach-->
array(
'<!--@foreach($arr as $key=>$val)--><li>item{$key} : {$val}</li><!--@endfor-->',
PHP_EOL . 'if($__Context->arr&&count($__Context->arr))foreach($__Context->arr as $__Context->key=>$__Context->val){ ?><li>item<?php echo $__Context->key ?> : <?php echo $__Context->val ?></li><?php } ?>'
),
// <!--@while--> ~ <!--@endwhile-->
array(
'<!--@while($item=$list->getItem())--><a href="{$v->link}">{$v->text}</a><!--@endwhile-->',
PHP_EOL.'while($__Context->item=$__Context->list->getItem()){ ?><a href="<?php echo $__Context->v->link ?>"><?php echo $__Context->v->text ?></a><?php } ?>'
),
// <!--@switch--> ~ <!--@case--> ~ <!--@break--> ~ <!--@default --> ~ <!--@endswitch-->
array(
'<dummy /><!--@switch($var)--> <!--@case("A")--> A<!--@break--> <!--@case(\'B\')-->B<!--@break--><!--@default-->C<!--@endswitch--><dummy />',
'?><dummy /><?php switch($__Context->var){;'.PHP_EOL.'case "A": ?> A<?php break;'.PHP_EOL.'case \'B\': ?>B<?php break;'.PHP_EOL.'default : ?>C<?php } ?><dummy />'
),
// invalid block statement
array(
'<dummy /><!--@xe($var)--><dummy />',
'?><dummy /><dummy />'
),
// {@ ...PHP_CODE...}
array(
'<before />{@$list_page = $page_no}<after />',
'?><before /><?php $__Context->list_page = $__Context->page_no ?><after />'
),
// %load_js_plugin
array(
'<dummy /><!--%load_js_plugin("ui")--><dummy />',
'?><dummy /><!--#JSPLUGIN:ui--><?php Context::loadJavascriptPlugin(\'ui\'); ?><dummy />'
),
// #include
array(
'<dummy /><!--#include("sample.html")--><div>This is another dummy</div>',
'?><dummy /><?php $__tpl=TemplateHandler::getInstance();echo $__tpl->compile(\'tests/unit/classes/template\',\'sample.html\') ?><div>This is another dummy</div>'
),
// <include target="file">
array(
'<dummy /><include target="../sample.html" /><div>This is another dummy</div>',
'?><dummy /><?php $__tpl=TemplateHandler::getInstance();echo $__tpl->compile(\'tests/unit/classes\',\'sample.html\') ?><div>This is another dummy</div>'
),
// <load target="../../modules/page/lang/lang.xml">
array(
'<dummy /><load target="../../../../modules/page/lang/lang.xml" /><dummy />',
'?><dummy /><?php Context::loadLang(\'modules/page/lang\'); ?><dummy />'
),
// <load target="style.css">
array(
'<dummy /><load target="css/style.css" /><dummy />',
'?><dummy /><!--#Meta:tests/unit/classes/template/css/style.css--><?php $__tmp=array(\'tests/unit/classes/template/css/style.css\',\'\',\'\',\'\');Context::loadFile($__tmp);unset($__tmp); ?><dummy />'
),
// <unload target="style.css">
array(
'<dummy /><unload target="css/style.css" /><dummy />',
'?><dummy /><?php Context::unloadFile(\'tests/unit/classes/template/css/style.css\',\'\',\'\'); ?><dummy />'
),
// <!--%import("../../modules/page/tpl/filter/insert_config.xml")-->
array(
'<dummy /><!--%import("../../../../modules/page/tpl/filter/insert_config.xml")--><dummy />',
'?><dummy /><?php require_once(\'./classes/xml/XmlJsFilter.class.php\');$__xmlFilter=new XmlJsFilter(\'modules/page/tpl/filter\',\'insert_config.xml\');$__xmlFilter->compile(); ?><dummy />'
),
// <!--%import("../script.js",type="body")-->
array(
'<dummy /><!--%import("../script.js",type="body")--><dummy />',
'?><dummy /><!--#Meta:tests/unit/classes/script.js--><?php $__tmp=array(\'tests/unit/classes/script.js\',\'body\',\'\',\'\');Context::loadFile($__tmp);unset($__tmp); ?><dummy />'
),
// <!--%unload("../script.js",type="body")-->
array(
'<dummy /><!--%unload("../script.js",type="body")--><dummy />',
'?><dummy /><?php Context::unloadFile(\'tests/unit/classes/script.js\',\'\'); ?><dummy />'
),
// comment
array(
'<dummy_before /><!--// this is a comment--><dummy_after />',
'?><dummy_before /><dummy_after />'
),
// self-closing tag
array(
'<meta charset="utf-8" cond="$foo">',
PHP_EOL . 'if($__Context->foo){ ?><meta charset="utf-8"><?php } ?>'
),
// relative path1
array(
'<img src="http://naver.com/naver.gif"><input type="image" src="../local.gif" />',
'?><img src="http://naver.com/naver.gif"><input type="image" src="/xe/tests/unit/classes/local.gif" />'
),
// relative path2
array(
'<img src="http://naver.com/naver.gif"><input type="image" src="../../../dir/local.gif" />',
'?><img src="http://naver.com/naver.gif"><input type="image" src="/xe/tests/dir/local.gif" />'
),
// error case
array(
'<a href="{$layout_info->index_url}" cond="$layout_info->logo_image"><img src="{$layout_info->logo_image}" alt="logo" border="0" /></a>',
PHP_EOL . 'if($__Context->layout_info->logo_image){ ?><a href="<?php echo $__Context->layout_info->index_url ?>"><img src="<?php echo $__Context->layout_info->logo_image ?>" alt="logo" border="0" /></a><?php } ?>'
),
// error case - ignore stylesheets
array(
'<style>body{background-color:black}</style>',
'?><style>body{background-color:black}</style>'
),
// error case - ignore json
array(
'<script>var json = {hello:"world"};</script>',
'?><script>var json = {hello:"world"};</script>'
),
// error case - inline javascript
array(
'<form onsubmit="jQuery(this).find(\'input\').each(function(){if(this.title==this.value)this.value=\'\';}); return procFilter(this, insert_comment)"></form>',
'?><form onsubmit="jQuery(this).find(\'input\').each(function(){if(this.title==this.value)this.value=\'\';}); return procFilter(this, insert_comment)"><input type="hidden" name="error_return_url" value="<?php echo htmlspecialchars(getRequestUriByServerEnviroment(), ENT_COMPAT | ENT_HTML401, \'UTF-8\', false) ?>" /><input type="hidden" name="act" value="<?php echo $__Context->act ?>" /><input type="hidden" name="mid" value="<?php echo $__Context->mid ?>" /><input type="hidden" name="vid" value="<?php echo $__Context->vid ?>" /></form>'
),
// issue 103
array(
'<load target="http://aaa.com/aaa.js" />',
'?><!--#Meta:http://aaa.com/aaa.js--><?php $__tmp=array(\'http://aaa.com/aaa.js\',\'\',\'\',\'\');Context::loadFile($__tmp);unset($__tmp); ?>'
),
// issue 135
array(
'<block loop="$_m_list_all=>$key,$val"><p>{$key}</p><div>Loop block {$val}</div></block>',
PHP_EOL . 'if($__Context->_m_list_all&&count($__Context->_m_list_all))foreach($__Context->_m_list_all as $__Context->key=>$__Context->val){ ?><p><?php echo $__Context->key ?></p><div>Loop block <?php echo $__Context->val ?></div><?php } ?>'
),
// issue 136
array(
'<br cond="$var==\'foo\'" />bar',
PHP_EOL . 'if($__Context->var==\'foo\'){ ?><br /><?php } ?>bar'
),
// issue 188
array(
'<div cond="$ii < $nn" loop="$dummy => $k, $v">Hello, world!</div>',
PHP_EOL . 'if($__Context->ii < $__Context->nn){;'.PHP_EOL.'if($__Context->dummy&&count($__Context->dummy))foreach($__Context->dummy as $__Context->k=>$__Context->v){ ?><div>Hello, world!</div><?php }} ?>'
),
// issue 190
array(
'<div cond="!($i >= $n)" loop="$dummy => $k, $v">Hello, world!</div>',
PHP_EOL . 'if(!($__Context->i >= $__Context->n)){;'.PHP_EOL.'if($__Context->dummy&&count($__Context->dummy))foreach($__Context->dummy as $__Context->k=>$__Context->v){ ?><div>Hello, world!</div><?php }} ?>'
),
// issue 183
array(
'<table><thead><tr><th loop="$vvvls => $vvv">{$vvv}</th></tr></thead>'."\n".'<tbody><tr><td>C</td><td>D</td></tr></tbody></table>',
'?><table><thead><tr><?php if($__Context->vvvls&&count($__Context->vvvls))foreach($__Context->vvvls as $__Context->vvv){ ?><th><?php echo $__Context->vvv ?></th><?php } ?></tr></thead>'."\n".'<tbody><tr><td>C</td><td>D</td></tr></tbody></table>'
),
// issue 512 - ignores <marquee>
array(
'<div class="topimgContex"><marquee direction="up" scrollamount="1" height="130" loop="infinity" behavior="lscro">{$lang->sl_show_topimgtext}</marquee></div>',
'?><div class="topimgContex"><marquee direction="up" scrollamount="1" height="130" loop="infinity" behavior="lscro"><?php echo $__Context->lang->sl_show_topimgtext ?></marquee></div>'
),
// issue 584
array(
'<img cond="$oBodex->display_extra_images[\'mobile\'] && $arr_extra && $arr_extra->bodex->mobile" src="./images/common/mobile.gif" title="mobile" alt="mobile" />',
PHP_EOL . 'if($__Context->oBodex->display_extra_images[\'mobile\'] && $__Context->arr_extra && $__Context->arr_extra->bodex->mobile){ ?><img src="./images/common/mobile.gif" title="mobile" alt="mobile" /><?php } ?>'
),
// issue 831
array(
"<li <!--@if(in_array(\$act, array(\n'dispNmsAdminGroupList',\n'dispNmsAdminInsertGroup',\n'dispNmsAdminGroupInfo',\n'dispNmsAdminDeleteGroup')))-->class=\"on\"<!--@endif-->>",
"?><li <?php if(in_array(\$__Context->act, array(\n'dispNmsAdminGroupList',\n'dispNmsAdminInsertGroup',\n'dispNmsAdminGroupInfo',\n'dispNmsAdminDeleteGroup'))){ ?>class=\"on\"<?php } ?>>"
),
// issue 746
array(
'<img src="../myxe/xe/img.png" />',
'?><img src="/xe/tests/unit/classes/myxe/xe/img.png" />'
),
// issue 696
array(
'{@ eval(\'$val = $document_srl;\')}',
PHP_EOL . 'eval(\'$__Context->val = $__Context->document_srl;\') ?>'
),
);
}
/**
* @dataProvider provider
*/
public function testParse($tpl, $expected)
{
$tmpl = new TemplateHandlerWrapper;
$tmpl->init(dirname(__FILE__), 'no_file.html');
$result = $tmpl->parse($tpl);
$this->assertEquals($result, $this->prefix.$expected);
}
public function testParse2()
{
$tmpl = new TemplateHandlerWrapper;
$tmpl->init(dirname(__FILE__), 'no_file.html');
$result = $tmpl->parse($tpl);
$this->assertEquals($result, '');
}
public function testCompileDirect()
{
$tmpl = TemplateHandler::getInstance();
$result = $tmpl->compileDirect(dirname(__FILE__), 'sample.html');
$result = trim($result);
$this->assertEquals($result, $this->prefix.PHP_EOL.'if($__Context->has_blog){ ?><a href="http://mygony.com">Taggon\'s blog</a><?php } ?>'.PHP_EOL.'<!--#Meta://external.host/js.js--><?php $__tmp=array(\'//external.host/js.js\',\'\',\'\',\'\');Context::loadFile($__tmp);unset($__tmp); ?>');
}
}
class TemplateHandlerWrapper extends \TemplateHandler {
private $inst;
function __construct() {
$this->inst = parent::getInstance();
}
public function init($tpl_path, $tpl_filename, $tpl_file = '') {
call_user_method('init', $this->inst, $tpl_path, $tpl_filename, $tpl_file);
}
public function parse($buff = null) {
return call_user_method('parse', $this->inst, $buff);
}
}

View file

@ -0,0 +1 @@
/* only for test */

View file

@ -0,0 +1,2 @@
<a href="http://mygony.com" cond="$has_blog">Taggon's blog</a>
<load target="//external.host/js.js" />

View file

@ -0,0 +1,208 @@
<?php
require_once _XE_PATH_.'classes/context/Context.class.php';
require_once _XE_PATH_.'classes/xml/XmlParser.class.php';
require_once _XE_PATH_.'classes/handler/Handler.class.php';
require_once _XE_PATH_.'classes/file/FileHandler.class.php';
require_once _XE_PATH_.'classes/validator/Validator.class.php';
class ValidatorTest extends \Codeception\TestCase\Test
{
protected function setUp()
{
global $lang;
$lang->filter = new stdClass;
$lang->filter->isnull = 'isnull';
$lang->filter->outofrange = 'outofrange';
$lang->filter->equalto = 'equalto';
}
public function testRequired()
{
$vd = new Validator();
$vd->addFilter('userid', array('required'=>'true'));
// given data
$this->assertFalse( $vd->validate(array('no-userid'=>'hello')) );
$this->assertTrue( $vd->validate(array('userid'=>'myuserid')) );
$this->assertFalse( $vd->validate(array('userid'=>'')) );
// context data
$this->assertFalse( $vd->validate() );
Context::set('userid', '', true);
$this->assertFalse( $vd->validate() );
Context::set('userid', 'myuserid', true);
$this->assertTrue( $vd->validate() );
$vd->removeFilter('userid');
$this->assertTrue( $vd->validate() );
}
public function testNamePattern()
{
$vd = new Validator();
$vd->addFilter('^user_', array('length'=>'5:'));
Context::set('user_123', 'abcd', true);
Context::set('user_456', '123', true);
$this->assertFalse( $vd->validate() );
Context::set('user_123', 'abcdefg', true);
$this->assertFalse( $vd->validate() );
Context::set('user_456', '123456', true);
$this->assertTrue( $vd->validate() );
}
public function testEqualTo()
{
$vd = new Validator();
$vd->addFilter('pass1', array('equalto'=>'pass2'));
Context::set('pass1', 'MyPassword', true);
$this->assertFalse( $vd->validate() );
Context::set('pass2', 'WorngPassword', true);
$this->assertFalse( $vd->validate() );
Context::set('pass2', 'MyPassword', true);
$this->assertTrue( $vd->validate() );
}
public function testArrayTrim()
{
$vd = new Validator();
$arr = array('red'=>'apple', 'yellow'=>'banana ', 'green'=>' papaya ');
$this->assertEquals($vd->arrayTrim($arr), array('red'=>'apple', 'yellow'=>'banana', 'green'=>'papaya'));
$this->assertEquals($vd->arrayTrim(' string '), 'string');
}
public function testLength()
{
$vd = new Validator();
$vd->addFilter('field1', array('length'=>'3:'));
$this->assertFalse( $vd->validate(array('field1'=>'ab')) );
$this->assertTrue( $vd->validate(array('field1'=>'abc')) );
$this->assertTrue( $vd->validate(array('field1'=>'abcd')) );
}
public function testCustomRule()
{
// regex
$vd = new Validator();
$customRules['regex_rule']['type'] = 'regex';
$customRules['regex_rule']['test'] = '/^[a-z]+$/';
$vd->addRule($customRules);
$vd->addFilter('regex_field', array('rule' => 'regex_rule'));
$this->assertTrue($vd->validate(array('regex_field' => 'abc')));
$this->assertFalse($vd->validate(array('regex_field' => 'ABC')));
// enum
$vd = new Validator();
$customRules['enum_rule']['type'] = 'enum';
$customRules['enum_rule']['test'] = 'a,b,c';
$vd->addRule($customRules);
$vd->addFilter('enum_field', array('rule' => 'enum_rule'));
$this->assertTrue($vd->validate(array('enum_field' => 'a')));
$this->assertFalse($vd->validate(array('enum_field' => 'd')));
// enum with custom delimiter
$vd = new Validator();
$customRules['enum_rule2']['type'] = 'enum';
$customRules['enum_rule2']['test'] = 'a@b@c';
$customRules['enum_rule2']['delim'] = '@';
$vd->addRule($customRules);
$vd->addFilter('enum_field2', array('rule' => 'enum_rule2'));
$this->assertTrue($vd->validate(array('enum_field2' => 'a')));
$this->assertFalse($vd->validate(array('enum_field2' => 'd')));
// expr
$vd = new Validator();
$customRules['expr_rule']['type'] = 'expr';
$customRules['expr_rule']['test'] = '$$ &lt; 10';
$vd->addRule($customRules);
$vd->addFilter('expr_field', array('rule' => 'expr_rule'));
$this->assertTrue($vd->validate(array('expr_field' => '5')));
$this->assertFalse($vd->validate(array('expr_field' => '15')));
}
public function testCustomRuleXml()
{
$vd = new Validator(dirname(__FILE__).'/customrule.xml');
$this->assertTrue($vd->validate(array('regex_field' => 'abc')));
$this->assertFalse($vd->validate(array('regex_field' => 'ABC')));
$this->assertTrue($vd->validate(array('enum_field' => 'a')));
$this->assertFalse($vd->validate(array('enum_field' => 'd')));
$this->assertTrue($vd->validate(array('enum_field2' => 'a')));
$this->assertFalse($vd->validate(array('enum_field2' => 'd')));
$this->assertTrue($vd->validate(array('expr_field' => '5')));
$this->assertFalse($vd->validate(array('expr_field' => '15')));
}
public function testCondition()
{
$vd = new Validator();
$data = array('greeting1'=>'hello');
// No condition
$vd->addFilter('greeting1', array('required'=>'true'));
$this->assertTrue($vd->validate($data));
// Now greeting2 being mandatory if greeting1 is 'Hello'
$vd->addFilter('greeting2', array('if'=>array('test'=>'$greeting1 == "Hello"', 'attr'=>'required', 'value'=>'true')));
// Because greeting1 is 'hello', including lowercase 'h', greeting2 isn't required yet.
$this->assertTrue($vd->validate($data));
// Change the value of greeting1. Greeting2 is required now
$data['greeting1'] = 'Hello';
$this->assertFalse($vd->validate($data));
$data['greeting2'] = 'World';
$this->assertTrue($vd->validate($data));
}
public function testConditionXml()
{
$vd = new Validator(dirname(__FILE__).'/condition.xml');
$data = array('greeting1'=>'hello');
$this->assertTrue($vd->validate($data));
// Change the value of greeting1. Greeting2 is required now
$data['greeting1'] = 'Hello';
$this->assertFalse($vd->validate($data));
$data['greeting2'] = 'World';
$this->assertTrue($vd->validate($data));
// javascript
$vd->setCacheDir(dirname(__FILE__));
$js = $vd->getJsPath();
$this->assertFileEquals($js, dirname(__FILE__).'/condition.en.js');
}
protected function tearDown()
{
// remove cache directory
$cache_dir = dirname(__FILE__).'/ruleset';
if(is_dir($cache_dir))
{
$files = (array)glob($cache_dir.'/*');
foreach($files as $file)
{
unlink($file);
}
rmdir($cache_dir);
}
}
}

View file

@ -0,0 +1,8 @@
(function($,v){
v=xe.getApp('validator')[0];if(!v)return;
v.cast('ADD_FILTER',['condition', {'greeting1':{required:true},'greeting2':{'if':[{test:'$greeting1 == \'Hello\'', attr:'required', value:'true'}]}}]);
v.cast('ADD_MESSAGE',['isnull','isnull']);
v.cast('ADD_MESSAGE',['outofrange','outofrange']);
v.cast('ADD_MESSAGE',['equalto','equalto']);
})(jQuery);

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<ruleset version="1.5.0">
<fields>
<field name="greeting1" required="true" />
<field name="greeting2">
<if test="$greeting1 == 'Hello'" attr="required" value="true" />
</field>
</fields>
</ruleset>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<ruleset version="1.5.0">
<customrules>
<rule name="regex_rule" type="regex" test="/^[a-z]+$/" />
<rule name="enum_rule" type="enum" test="a,b,c" />
<rule name="enum_rule2" type="enum" test="a@b@c" delim="@" />
<rule name="expr_rule" type="expr" test="$$ &lt; 10" />
</customrules>
<fields>
<field name="regex_field" rule="regex_rule" />
<field name="enum_field" rule="enum_rule" />
<field name="enum_field2" rule="enum_rule2" />
<field name="expr_field" rule="expr_rule" />
</fields>
</ruleset>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<ruleset version="1.5.0">
<customrules>
</customrules>
<fields>
<field name="nick_name" length="1:20"/>
<field name="password" length="1:20"/>
<field name="email_address" rule="email" length=":250" />
<field name="homepage" rule="url" length=":250" />
<field name="title" required="true" length="1:250"/>
<field name="content" required="true"/>
<field name="category_srl" required="true" rule="number" default="0" />
</fields>
</ruleset>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<ruleset>
<fields>
<field name="userid" required="true" length="5:10" rule="userid" default="idididid" />
<field name="password" required="true" />
</fields>
</ruleset>