Make separate setups for integration and unit tests

This commit is contained in:
wxa
2018-10-17 14:34:17 +03:00
parent 87e515b89d
commit 9092aa3029
10 changed files with 752 additions and 334 deletions

View File

@@ -158,6 +158,26 @@ class RoboFile extends \Robo\Tasks {
$command = 'vendor/bin/codecept run unit -c codeception.unit.yml'; $command = 'vendor/bin/codecept run unit -c codeception.unit.yml';
if($opts['file']) {
$command .= ' -f ' . $opts['file'];
}
if($opts['xml']) {
$command .= ' --xml';
}
if($opts['debug']) {
$command .= ' --debug';
}
return $this->_exec($command);
}
function testIntegration(array $opts=['file' => null, 'xml' => false, 'multisite' => false, 'debug' => false]) {
$this->loadEnv();
$command = 'vendor/bin/codecept run integration -c codeception.integration.yml';
if($opts['multisite']) { if($opts['multisite']) {
$command = 'MULTISITE=true ' . $command; $command = 'MULTISITE=true ' . $command;
} }
@@ -177,8 +197,8 @@ class RoboFile extends \Robo\Tasks {
return $this->_exec($command); return $this->_exec($command);
} }
function testMultisiteUnit($opts=['file' => null, 'xml' => false, 'multisite' => true]) { function testMultisiteIntegration($opts=['file' => null, 'xml' => false, 'multisite' => true]) {
return $this->testUnit($opts); return $this->testIntegration($opts);
} }
function testCoverage($opts=['file' => null, 'xml' => false]) { function testCoverage($opts=['file' => null, 'xml' => false]) {
@@ -219,10 +239,14 @@ class RoboFile extends \Robo\Tasks {
return $this->_exec('vendor/bin/security-checker security:check --format=simple'); return $this->_exec('vendor/bin/security-checker security:check --format=simple');
} }
function testDebug($opts=['file' => null, 'xml' => false, 'debug' => true]) { function testDebugUnit($opts=['file' => null, 'xml' => false, 'debug' => true]) {
return $this->testUnit($opts); return $this->testUnit($opts);
} }
function testDebugIntegration($opts=['file' => null, 'xml' => false, 'debug' => true]) {
return $this->testIntegration($opts);
}
function testAcceptance($opts=['file' => null, 'skip-deps' => false]) { function testAcceptance($opts=['file' => null, 'skip-deps' => false]) {
return $this->_exec( return $this->_exec(
'COMPOSE_HTTP_TIMEOUT=200 docker-compose run ' . 'COMPOSE_HTTP_TIMEOUT=200 docker-compose run ' .
@@ -290,8 +314,8 @@ class RoboFile extends \Robo\Tasks {
'./vendor/bin/phpcs '. './vendor/bin/phpcs '.
'--standard=./tasks/code_sniffer/MailPoet '. '--standard=./tasks/code_sniffer/MailPoet '.
'--runtime-set testVersion 5.5-7.2 '. '--runtime-set testVersion 5.5-7.2 '.
'--ignore=./tests/unit/_bootstrap.php '. '--ignore=./tests/unit/_bootstrap.php,./tests/unit/_fixtures.php,./tests/integration/_bootstrap.php,./tests/integration/_fixtures.php '.
'tests/unit/ tests/acceptance tests/DataFactories '. 'tests/unit tests/integration tests/acceptance tests/DataFactories '.
$severityFlag $severityFlag
) )
->run(); ->run();

View File

@@ -0,0 +1,34 @@
actor: Tester
paths:
tests: tests
log: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs
settings:
bootstrap: _bootstrap.php
colors: true
memory_limit: 1024M
log: true
strict_xml: true
extensions:
enabled:
- Codeception\Extension\RunFailed
modules:
config:
Db:
dsn: ''
user: ''
password: ''
dump: tests/_data/dump.sql
coverage:
enabled: true
whitelist:
include:
- lib/*
exclude:
- lib/Config/PopulatorData/*
- lib/Util/Sudzy/*
- lib/Util/CSS.php
- lib/Util/Helpers.php
- lib/Util/XLSXWriter.php

View File

@@ -1,147 +1 @@
<?php <?php
if((boolean)getenv('MULTISITE') === true) {
// REQUEST_URI needs to be set for WP to load the proper subsite where MailPoet is activated
$_SERVER['REQUEST_URI'] = '/' . getenv('WP_TEST_MULTISITE_SLUG');
$wp_load_file = getenv('WP_TEST_PATH_MULTISITE') . '/wp-load.php';
} else {
$wp_load_file = getenv('WP_TEST_PATH') . '/wp-load.php';
}
require_once($wp_load_file);
$console = new \Codeception\Lib\Console\Output([]);
$console->writeln('Loading WP core... (' . $wp_load_file . ')');
$console->writeln('Cleaning up database...');
$models = array(
'CustomField',
'Form',
'Newsletter',
'NewsletterLink',
'NewsletterPost',
'NewsletterSegment',
'NewsletterTemplate',
'NewsletterOption',
'NewsletterOptionField',
'Segment',
'Log',
'ScheduledTask',
'ScheduledTaskSubscriber',
'SendingQueue',
'Setting',
'Subscriber',
'SubscriberCustomField',
'SubscriberSegment',
'SubscriberIP',
'StatisticsOpens',
'StatisticsClicks',
'StatisticsNewsletters',
'StatisticsUnsubscribes'
);
$destroy = function($model) {
$class = new \ReflectionClass('\MailPoet\Models\\' . $model);
$table = $class->getStaticPropertyValue('_table');
$db = ORM::getDb();
$db->beginTransaction();
$db->exec('TRUNCATE ' . $table);
$db->commit();
};
array_map($destroy, $models);
$cacheDir = '/tmp';
if(is_dir(getenv('WP_TEST_CACHE_PATH'))) {
$cacheDir = getenv('WP_TEST_CACHE_PATH');
}
$console->writeln('Clearing AspectMock cache...');
exec('rm -rf ' . $cacheDir . '/_transformation.cache');
$console->writeln('Initializing AspectMock library...');
$kernel = \AspectMock\Kernel::getInstance();
$kernel->init(
array(
'debug' => true,
'appDir' => __DIR__ . '/../',
'cacheDir' => $cacheDir,
'includePaths' => [__DIR__ . '/../lib'],
'appDir' => __DIR__ . '/../'
)
);
// This hook throws an 'Undefined index: SERVER_NAME' error in CLI mode,
// the action is called in ConflictResolverTest
remove_filter('admin_print_styles', 'wp_resource_hints', 1);
abstract class MailPoetTest extends \Codeception\TestCase\Test {
protected $backupGlobals = true;
protected $backupGlobalsBlacklist = array(
'app',
'post',
'authordata',
'currentday',
'currentmonth',
'page',
'pages',
'multipage',
'more',
'numpages',
'is_iphone',
'is_chrome',
'is_safari',
'is_NS4',
'is_opera',
'is_macIE',
'is_winIE',
'is_gecko',
'is_lynx',
'is_IE',
'is_apache',
'is_IIS',
'is_iis7',
'wp_version',
'wp_db_version',
'tinymce_version',
'manifest_version',
'required_php_version',
'required_mysql_version',
'super_admins',
'wp_query',
'wp_rewrite',
'wp',
'wpdb',
'wp_locale',
'wp_admin_bar',
'wp_roles',
'wp_meta_boxes',
'wp_registered_sidebars',
'wp_registered_widgets',
'wp_registered_widget_controls',
'wp_registered_widget_updates',
'pagenow',
'post_type',
'allowedposttags',
'allowedtags',
'menu'
);
protected $backupStaticAttributes = false;
protected $runTestInSeparateProcess = false;
protected $preserveGlobalState = false;
protected $inIsolation = false;
/**
* Call protected/private method of a class.
*
* @param object &$object Instantiated object that we will run method on.
* @param string $methodName Method name to call
* @param array $parameters Array of parameters to pass into method.
*
* @return mixed Method return.
*/
public function invokeMethod(&$object, $methodName, array $parameters = array()) {
$reflection = new \ReflectionClass(get_class($object));
$method = $reflection->getMethod($methodName);
$method->setAccessible(true);
return $method->invokeArgs($object, $parameters);
}
}

View File

@@ -0,0 +1,63 @@
<?php
/**
* 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 \Codeception\Lib\Friend haveFriend($name, $actorClass = null)
*
* @SuppressWarnings(PHPMD)
*/
class IntegrationTester extends \Codeception\Actor {
use _generated\IntegrationTesterActions;
// generate random users
function generateSubscribers($count, $data = array()) {
for($i = 0; $i < $count; $i++) {
$this->generateSubscriber($data);
}
}
function generateSubscriber($data = array()) {
$subscriber_data = array(
'email' => sprintf('user%s@mailpoet.com', uniqid()),
'first_name' => $this->generateName(),
'last_name' => $this->generateName()
);
$subscriber = \MailPoet\Models\Subscriber::create();
$subscriber->hydrate(array_merge($subscriber_data, $data));
$subscriber->save();
}
protected function generateName() {
$name = '';
$length = mt_rand(6, 12);
$vowels = 'aeiouy';
$consonants = 'bcdfgjklmnpqrstvwxz';
$specials = ' \'';
$alphabet = $consonants.$vowels;
$charset = $specials.$alphabet;
// pick first letter in alphabet
$name .= $alphabet{mt_rand(0, strlen($alphabet) - 1)};
for($i = 0; $i < $length; $i++) {
$name .= $charset{mt_rand(0, strlen($charset) - 1)};
}
// pick last letter in alphabet
$name .= $alphabet{mt_rand(0, strlen($alphabet) - 1)};
return ucfirst($name);
}
}

View File

@@ -0,0 +1,13 @@
# Codeception Test Suite Configuration
#
# Suite for unit (internal) tests.
actor: IntegrationTester
settings:
bootstrap: _bootstrap.php
modules:
enabled:
- Asserts
- \Helper\Unit
- \Helper\WordPress
error_level: E_ALL

View File

@@ -1,182 +1,149 @@
<?php <?php
use Codeception\Util\Fixtures;
use MailPoet\Models\Subscriber; if((boolean)getenv('MULTISITE') === true) {
// REQUEST_URI needs to be set for WP to load the proper subsite where MailPoet is activated
$newsletter_body_text = $_SERVER['REQUEST_URI'] = '/' . getenv('WP_TEST_MULTISITE_SLUG');
$wp_load_file = getenv('WP_TEST_PATH_MULTISITE') . '/wp-load.php';
Fixtures::add( } else {
'newsletter_body_template', $wp_load_file = getenv('WP_TEST_PATH') . '/wp-load.php';
'{ }
"content": { require_once($wp_load_file);
"type": "container",
"orientation": "vertical", $console = new \Codeception\Lib\Console\Output([]);
"blocks": [ $console->writeln('Loading WP core... (' . $wp_load_file . ')');
{
"type": "container", $console->writeln('Cleaning up database...');
"styles": { "block": {} }, $models = array(
"orientation": "horizontal", 'CustomField',
"blocks": [ 'Form',
{ 'Newsletter',
"type": "container", 'NewsletterLink',
"orientation": "vertical", 'NewsletterPost',
"styles": { "block": {} }, 'NewsletterSegment',
"blocks": [ 'NewsletterTemplate',
{ 'NewsletterOption',
"type": "text", 'NewsletterOptionField',
"text": "<a href=\"[link:newsletter_view_in_browser_url]\">View in browser link</a> <a data-post-id=\"10\" href=\"http://example.com\">Post link</a> Hello [subscriber:firstname | default:test] <a href=\"[link:subscription_unsubscribe_url]\">Unsubscribe link</a> <a href=\"[link:subscription_manage_url]\">Manage subscription link</a> <img src=\"http://example.com/image with space.jpg\"> <a href=\"http://example.com/link with space.jpg\">Link with space</a>" 'Segment',
} 'Log',
] 'ScheduledTask',
} 'ScheduledTaskSubscriber',
] 'SendingQueue',
} 'Setting',
] 'Subscriber',
} 'SubscriberCustomField',
}' 'SubscriberSegment',
); 'SubscriberIP',
'StatisticsOpens',
Fixtures::add( 'StatisticsClicks',
'newsletter_subject_template', 'StatisticsNewsletters',
'Newsletter for [subscriber:firstname]' 'StatisticsUnsubscribes'
); );
$destroy = function($model) {
Fixtures::add( $class = new \ReflectionClass('\MailPoet\Models\\' . $model);
'subscriber_template', $table = $class->getStaticPropertyValue('_table');
array( $db = ORM::getDb();
'first_name' => 'John', $db->beginTransaction();
'last_name' => 'John', $db->exec('TRUNCATE ' . $table);
'email' => 'john.doe@example.com' $db->commit();
) };
); array_map($destroy, $models);
Fixtures::add( $cacheDir = '/tmp';
'form_body_template', if(is_dir(getenv('WP_TEST_CACHE_PATH'))) {
array( $cacheDir = getenv('WP_TEST_CACHE_PATH');
array( }
'type' => 'text',
'name' => 'First name', $console->writeln('Clearing AspectMock cache...');
'id' => 'first_name', exec('rm -rf ' . $cacheDir . '/_transformation.cache');
'unique' => '1',
'static' => '0', $console->writeln('Initializing AspectMock library...');
'params' => $kernel = \AspectMock\Kernel::getInstance();
array( $kernel->init(
'label' => 'First name', array(
), 'debug' => true,
'position' => '1', 'appDir' => __DIR__ . '/../',
), 'cacheDir' => $cacheDir,
array( 'includePaths' => [__DIR__ . '/../lib'],
'type' => 'text', 'appDir' => __DIR__ . '/../'
'name' => 'Nickname', )
'id' => '4', );
'unique' => '1',
'static' => '0', // This hook throws an 'Undefined index: SERVER_NAME' error in CLI mode,
'params' => // the action is called in ConflictResolverTest
array( remove_filter('admin_print_styles', 'wp_resource_hints', 1);
'label' => 'Nickname',
), abstract class MailPoetTest extends \Codeception\TestCase\Test {
'position' => '2', protected $backupGlobals = true;
), protected $backupGlobalsBlacklist = array(
array( 'app',
'type' => 'text', 'post',
'name' => 'Age', 'authordata',
'id' => '2', 'currentday',
'unique' => '1', 'currentmonth',
'static' => '0', 'page',
'params' => 'pages',
array( 'multipage',
'required' => '', 'more',
'validate' => 'number', 'numpages',
'label' => 'Age', 'is_iphone',
), 'is_chrome',
'position' => '3', 'is_safari',
), 'is_NS4',
array ( 'is_opera',
'type' => 'divider', 'is_macIE',
'name' => 'Divider', 'is_winIE',
'id' => 'divider', 'is_gecko',
'unique' => '0', 'is_lynx',
'static' => '0', 'is_IE',
'params' => '', 'is_apache',
'position' => '4', 'is_IIS',
), 'is_iis7',
array ( 'wp_version',
'type' => 'radio', 'wp_db_version',
'name' => '3-way choice', 'tinymce_version',
'id' => '3', 'manifest_version',
'unique' => '1', 'required_php_version',
'static' => '0', 'required_mysql_version',
'params' => 'super_admins',
array ( 'wp_query',
'values' => 'wp_rewrite',
array ( 'wp',
0 => 'wpdb',
array ( 'wp_locale',
'value' => '1', 'wp_admin_bar',
), 'wp_roles',
1 => 'wp_meta_boxes',
array ( 'wp_registered_sidebars',
'value' => '2', 'wp_registered_widgets',
), 'wp_registered_widget_controls',
2 => 'wp_registered_widget_updates',
array ( 'pagenow',
'value' => '3', 'post_type',
), 'allowedposttags',
), 'allowedtags',
'required' => '', 'menu'
'label' => '3-way choice', );
), protected $backupStaticAttributes = false;
'position' => '5', protected $runTestInSeparateProcess = false;
), protected $preserveGlobalState = false;
array ( protected $inIsolation = false;
'type' => 'html',
'name' => 'Custom text or HTML', /**
'id' => 'html', * Call protected/private method of a class.
'unique' => '0', *
'static' => '0', * @param object &$object Instantiated object that we will run method on.
'params' => * @param string $methodName Method name to call
array ( * @param array $parameters Array of parameters to pass into method.
'text' => 'Subscribe to our newsletter and join [mailpoet_subscribers_count] other subscribers.', *
), * @return mixed Method return.
'position' => '6', */
), public function invokeMethod(&$object, $methodName, array $parameters = array()) {
array( $reflection = new \ReflectionClass(get_class($object));
'type' => 'text', $method = $reflection->getMethod($methodName);
'name' => 'Email', $method->setAccessible(true);
'id' => 'email',
'unique' => '0', return $method->invokeArgs($object, $parameters);
'static' => '1', }
'params' => }
array(
'label' => 'Email', include '_fixtures.php';
'required' => 'true',
),
'position' => '7',
),
array(
'type' => 'submit',
'name' => 'Submit',
'id' => 'submit',
'unique' => '0',
'static' => '1',
'params' =>
array(
'label' => 'Subscribe!',
),
'position' => '8',
),
)
);
/**
* Simple class mocking dynamic segment filter.
*/
class DynamicSegmentFilter {
protected $ids;
function __construct($ids) {
$this->ids = $ids;
}
public function toSql($orm) {
return $orm->whereIn(Subscriber::$_table . '.id', $this->ids);
}
}

View File

@@ -0,0 +1,182 @@
<?php
use Codeception\Util\Fixtures;
use MailPoet\Models\Subscriber;
$newsletter_body_text =
Fixtures::add(
'newsletter_body_template',
'{
"content": {
"type": "container",
"orientation": "vertical",
"blocks": [
{
"type": "container",
"styles": { "block": {} },
"orientation": "horizontal",
"blocks": [
{
"type": "container",
"orientation": "vertical",
"styles": { "block": {} },
"blocks": [
{
"type": "text",
"text": "<a href=\"[link:newsletter_view_in_browser_url]\">View in browser link</a> <a data-post-id=\"10\" href=\"http://example.com\">Post link</a> Hello [subscriber:firstname | default:test] <a href=\"[link:subscription_unsubscribe_url]\">Unsubscribe link</a> <a href=\"[link:subscription_manage_url]\">Manage subscription link</a> <img src=\"http://example.com/image with space.jpg\"> <a href=\"http://example.com/link with space.jpg\">Link with space</a>"
}
]
}
]
}
]
}
}'
);
Fixtures::add(
'newsletter_subject_template',
'Newsletter for [subscriber:firstname]'
);
Fixtures::add(
'subscriber_template',
array(
'first_name' => 'John',
'last_name' => 'John',
'email' => 'john.doe@example.com'
)
);
Fixtures::add(
'form_body_template',
array(
array(
'type' => 'text',
'name' => 'First name',
'id' => 'first_name',
'unique' => '1',
'static' => '0',
'params' =>
array(
'label' => 'First name',
),
'position' => '1',
),
array(
'type' => 'text',
'name' => 'Nickname',
'id' => '4',
'unique' => '1',
'static' => '0',
'params' =>
array(
'label' => 'Nickname',
),
'position' => '2',
),
array(
'type' => 'text',
'name' => 'Age',
'id' => '2',
'unique' => '1',
'static' => '0',
'params' =>
array(
'required' => '',
'validate' => 'number',
'label' => 'Age',
),
'position' => '3',
),
array (
'type' => 'divider',
'name' => 'Divider',
'id' => 'divider',
'unique' => '0',
'static' => '0',
'params' => '',
'position' => '4',
),
array (
'type' => 'radio',
'name' => '3-way choice',
'id' => '3',
'unique' => '1',
'static' => '0',
'params' =>
array (
'values' =>
array (
0 =>
array (
'value' => '1',
),
1 =>
array (
'value' => '2',
),
2 =>
array (
'value' => '3',
),
),
'required' => '',
'label' => '3-way choice',
),
'position' => '5',
),
array (
'type' => 'html',
'name' => 'Custom text or HTML',
'id' => 'html',
'unique' => '0',
'static' => '0',
'params' =>
array (
'text' => 'Subscribe to our newsletter and join [mailpoet_subscribers_count] other subscribers.',
),
'position' => '6',
),
array(
'type' => 'text',
'name' => 'Email',
'id' => 'email',
'unique' => '0',
'static' => '1',
'params' =>
array(
'label' => 'Email',
'required' => 'true',
),
'position' => '7',
),
array(
'type' => 'submit',
'name' => 'Submit',
'id' => 'submit',
'unique' => '0',
'static' => '1',
'params' =>
array(
'label' => 'Subscribe!',
),
'position' => '8',
),
)
);
/**
* Simple class mocking dynamic segment filter.
*/
class DynamicSegmentFilter {
protected $ids;
function __construct($ids) {
$this->ids = $ids;
}
public function toSql($orm) {
return $orm->whereIn(Subscriber::$_table . '.id', $this->ids);
}
}

View File

@@ -2,7 +2,7 @@
# #
# Suite for unit (internal) tests. # Suite for unit (internal) tests.
class_name: UnitTester actor: UnitTester
settings: settings:
bootstrap: _bootstrap.php bootstrap: _bootstrap.php
modules: modules:

99
tests/unit/_bootstrap.php Normal file
View File

@@ -0,0 +1,99 @@
<?php
$console = new \Codeception\Lib\Console\Output([]);
$cacheDir = '/tmp';
if(is_dir(getenv('WP_TEST_CACHE_PATH'))) {
$cacheDir = getenv('WP_TEST_CACHE_PATH');
}
$console->writeln('Clearing AspectMock cache...');
exec('rm -rf ' . $cacheDir . '/_transformation.cache');
$console->writeln('Initializing AspectMock library...');
$kernel = \AspectMock\Kernel::getInstance();
$kernel->init(
array(
'debug' => true,
'appDir' => __DIR__ . '/../',
'cacheDir' => $cacheDir,
'includePaths' => [__DIR__ . '/../lib'],
'appDir' => __DIR__ . '/../'
)
);
abstract class MailPoetTest extends \Codeception\TestCase\Test {
protected $backupGlobals = true;
protected $backupGlobalsBlacklist = array(
'app',
'post',
'authordata',
'currentday',
'currentmonth',
'page',
'pages',
'multipage',
'more',
'numpages',
'is_iphone',
'is_chrome',
'is_safari',
'is_NS4',
'is_opera',
'is_macIE',
'is_winIE',
'is_gecko',
'is_lynx',
'is_IE',
'is_apache',
'is_IIS',
'is_iis7',
'wp_version',
'wp_db_version',
'tinymce_version',
'manifest_version',
'required_php_version',
'required_mysql_version',
'super_admins',
'wp_query',
'wp_rewrite',
'wp',
'wpdb',
'wp_locale',
'wp_admin_bar',
'wp_roles',
'wp_meta_boxes',
'wp_registered_sidebars',
'wp_registered_widgets',
'wp_registered_widget_controls',
'wp_registered_widget_updates',
'pagenow',
'post_type',
'allowedposttags',
'allowedtags',
'menu'
);
protected $backupStaticAttributes = false;
protected $runTestInSeparateProcess = false;
protected $preserveGlobalState = false;
protected $inIsolation = false;
/**
* Call protected/private method of a class.
*
* @param object &$object Instantiated object that we will run method on.
* @param string $methodName Method name to call
* @param array $parameters Array of parameters to pass into method.
*
* @return mixed Method return.
*/
public function invokeMethod(&$object, $methodName, array $parameters = array()) {
$reflection = new \ReflectionClass(get_class($object));
$method = $reflection->getMethod($methodName);
$method->setAccessible(true);
return $method->invokeArgs($object, $parameters);
}
}
include '_fixtures.php';

182
tests/unit/_fixtures.php Normal file
View File

@@ -0,0 +1,182 @@
<?php
use Codeception\Util\Fixtures;
use MailPoet\Models\Subscriber;
$newsletter_body_text =
Fixtures::add(
'newsletter_body_template',
'{
"content": {
"type": "container",
"orientation": "vertical",
"blocks": [
{
"type": "container",
"styles": { "block": {} },
"orientation": "horizontal",
"blocks": [
{
"type": "container",
"orientation": "vertical",
"styles": { "block": {} },
"blocks": [
{
"type": "text",
"text": "<a href=\"[link:newsletter_view_in_browser_url]\">View in browser link</a> <a data-post-id=\"10\" href=\"http://example.com\">Post link</a> Hello [subscriber:firstname | default:test] <a href=\"[link:subscription_unsubscribe_url]\">Unsubscribe link</a> <a href=\"[link:subscription_manage_url]\">Manage subscription link</a> <img src=\"http://example.com/image with space.jpg\"> <a href=\"http://example.com/link with space.jpg\">Link with space</a>"
}
]
}
]
}
]
}
}'
);
Fixtures::add(
'newsletter_subject_template',
'Newsletter for [subscriber:firstname]'
);
Fixtures::add(
'subscriber_template',
array(
'first_name' => 'John',
'last_name' => 'John',
'email' => 'john.doe@example.com'
)
);
Fixtures::add(
'form_body_template',
array(
array(
'type' => 'text',
'name' => 'First name',
'id' => 'first_name',
'unique' => '1',
'static' => '0',
'params' =>
array(
'label' => 'First name',
),
'position' => '1',
),
array(
'type' => 'text',
'name' => 'Nickname',
'id' => '4',
'unique' => '1',
'static' => '0',
'params' =>
array(
'label' => 'Nickname',
),
'position' => '2',
),
array(
'type' => 'text',
'name' => 'Age',
'id' => '2',
'unique' => '1',
'static' => '0',
'params' =>
array(
'required' => '',
'validate' => 'number',
'label' => 'Age',
),
'position' => '3',
),
array (
'type' => 'divider',
'name' => 'Divider',
'id' => 'divider',
'unique' => '0',
'static' => '0',
'params' => '',
'position' => '4',
),
array (
'type' => 'radio',
'name' => '3-way choice',
'id' => '3',
'unique' => '1',
'static' => '0',
'params' =>
array (
'values' =>
array (
0 =>
array (
'value' => '1',
),
1 =>
array (
'value' => '2',
),
2 =>
array (
'value' => '3',
),
),
'required' => '',
'label' => '3-way choice',
),
'position' => '5',
),
array (
'type' => 'html',
'name' => 'Custom text or HTML',
'id' => 'html',
'unique' => '0',
'static' => '0',
'params' =>
array (
'text' => 'Subscribe to our newsletter and join [mailpoet_subscribers_count] other subscribers.',
),
'position' => '6',
),
array(
'type' => 'text',
'name' => 'Email',
'id' => 'email',
'unique' => '0',
'static' => '1',
'params' =>
array(
'label' => 'Email',
'required' => 'true',
),
'position' => '7',
),
array(
'type' => 'submit',
'name' => 'Submit',
'id' => 'submit',
'unique' => '0',
'static' => '1',
'params' =>
array(
'label' => 'Subscribe!',
),
'position' => '8',
),
)
);
/**
* Simple class mocking dynamic segment filter.
*/
class DynamicSegmentFilter {
protected $ids;
function __construct($ids) {
$this->ids = $ids;
}
public function toSql($orm) {
return $orm->whereIn(Subscriber::$_table . '.id', $this->ids);
}
}