diff --git a/RoboFile.php b/RoboFile.php index 8ad4575275..7c2ecfbd03 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -1,122 +1,122 @@ -_exec('./composer.phar install'); - $this->_exec('npm install'); - } - - function update() { - $this->say(getenv('WP_TEST_URL')); - $this->_exec('./composer.phar update'); - $this->_exec('npm update'); - } - - function watch() { - $css_files = array( - 'assets/css/src/admin.styl', - 'assets/css/src/rtl.styl' - ); - - $js_files = glob('assets/js/src/*.js'); - - $this->taskWatch() - ->monitor($js_files, function() { - $this->compileJavascript(); - }) - ->monitor($css_files, function() use($css_files) { - $this->compileStyles($css_files); - }) - ->run(); - } - - function compileJavascript() { - $this->_exec('./node_modules/webpack/bin/webpack.js'); - } - - protected function compileStyles($files = array()) { - if(empty($files)) { return; } - - $this->_exec(join(' ', array( - './node_modules/stylus/bin/stylus', - '-u nib', - '-w', - join(' ', $files), - '-o assets/css/' - ))); - } - - function makepot() { - $this->_exec('grunt makepot'. - ' --gruntfile '.__DIR__.'/tasks/makepot/makepot.js'. - ' --base_path '.__DIR__ - ); - } - - function pushpot() { - $this->_exec('grunt pushpot'. - ' --gruntfile '.__DIR__.'/tasks/makepot/makepot.js'. - ' --base_path '.__DIR__ - ); - } - - function testUnit($singleUnit = null) { - $this->loadEnv(); - $this->_exec('vendor/bin/codecept build'); - $this->_exec('vendor/bin/codecept run unit ' . (($singleUnit) ? $singleUnit : '')); - } - - function testAcceptance() { - $this->loadEnv(); - $this->_exec('vendor/bin/codecept build'); - $this - ->taskExec('phantomjs --webdriver=4444') - ->background() - ->run(); - sleep(2); - $this->_exec('vendor/bin/codecept run acceptance'); - } - - function testJavascript() { - $this->compileJavascript(); - - $this->_exec(join(' ', array( - './node_modules/mocha/bin/mocha', - '-r tests/javascript/mochaTestHelper.js', - 'tests/javascript/testBundles/**/*.js' - ))); - } - - function testAll() { - $this->loadEnv(); - $this->_exec('vendor/bin/codecept build'); - $this - ->taskexec('phantomjs --webdriver=4444') - ->background() - ->run(); - sleep(2); - $this->_exec('vendor/bin/codecept run'); - } - - function testDebug() { - $this->_exec('vendor/bin/codecept build'); - $this->loadEnv(); - $this->_exec('vendor/bin/codecept run unit --debug'); - } - - protected function loadEnv() { - $dotenv = new Dotenv\Dotenv(__DIR__); - $dotenv->load(); - - $this - ->taskWriteToFile('tests/acceptance.suite.yml') - ->textFromFile('tests/acceptance.suite.src') - ->run(); - - $this - ->taskReplaceInFile('tests/acceptance.suite.yml') - ->regex("/url.*/") - ->to('url: ' . "'" . getenv('WP_TEST_URL'). "'") - ->run(); - } -} +_exec('./composer.phar install'); + $this->_exec('npm install'); + } + + function update() { + $this->say(getenv('WP_TEST_URL')); + $this->_exec('./composer.phar update'); + $this->_exec('npm update'); + } + + function watch() { + $css_files = array( + 'assets/css/src/admin.styl', + 'assets/css/src/rtl.styl' + ); + + $js_files = glob('assets/js/src/*.js'); + + $this->taskWatch() + ->monitor($js_files, function() { + $this->compileJavascript(); + }) + ->monitor($css_files, function() use($css_files) { + $this->compileStyles($css_files); + }) + ->run(); + } + + function compileJavascript() { + $this->_exec('./node_modules/webpack/bin/webpack.js'); + } + + protected function compileStyles($files = array()) { + if(empty($files)) { return; } + + $this->_exec(join(' ', array( + './node_modules/stylus/bin/stylus', + '-u nib', + '-w', + join(' ', $files), + '-o assets/css/' + ))); + } + + function makepot() { + $this->_exec('grunt makepot'. + ' --gruntfile '.__DIR__.'/tasks/makepot/makepot.js'. + ' --base_path '.__DIR__ + ); + } + + function pushpot() { + $this->_exec('grunt pushpot'. + ' --gruntfile '.__DIR__.'/tasks/makepot/makepot.js'. + ' --base_path '.__DIR__ + ); + } + + function testUnit($singleUnit = null) { + $this->loadEnv(); + $this->_exec('vendor/bin/codecept build'); + $this->_exec('vendor/bin/codecept run unit ' . (($singleUnit) ? $singleUnit : '')); + } + + function testAcceptance() { + $this->loadEnv(); + $this->_exec('vendor/bin/codecept build'); + $this + ->taskExec('phantomjs --webdriver=4444') + ->background() + ->run(); + sleep(2); + $this->_exec('vendor/bin/codecept run acceptance'); + } + + function testJavascript() { + $this->compileJavascript(); + + $this->_exec(join(' ', array( + './node_modules/mocha/bin/mocha', + '-r tests/javascript/mochaTestHelper.js', + 'tests/javascript/testBundles/**/*.js' + ))); + } + + function testAll() { + $this->loadEnv(); + $this->_exec('vendor/bin/codecept build'); + $this + ->taskexec('phantomjs --webdriver=4444') + ->background() + ->run(); + sleep(2); + $this->_exec('vendor/bin/codecept run'); + } + + function testDebug() { + $this->_exec('vendor/bin/codecept build'); + $this->loadEnv(); + $this->_exec('vendor/bin/codecept run unit --debug'); + } + + protected function loadEnv() { + $dotenv = new Dotenv\Dotenv(__DIR__); + $dotenv->load(); + + $this + ->taskWriteToFile('tests/acceptance.suite.yml') + ->textFromFile('tests/acceptance.suite.src') + ->run(); + + $this + ->taskReplaceInFile('tests/acceptance.suite.yml') + ->regex("/url.*/") + ->to('url: ' . "'" . getenv('WP_TEST_URL'). "'") + ->run(); + } +} diff --git a/RoboFile.php.orig b/RoboFile.php.orig new file mode 100644 index 0000000000..37131d115b --- /dev/null +++ b/RoboFile.php.orig @@ -0,0 +1,133 @@ +_exec('./composer.phar install'); + $this->_exec('npm install'); + } + + function update() { + $this->say(getenv('WP_TEST_URL')); + $this->_exec('./composer.phar update'); + $this->_exec('npm update'); + } + + function watch() { + $css_files = array( + 'assets/css/src/admin.styl', + 'assets/css/src/rtl.styl' + ); + +<<<<<<< HEAD + $command = array( + './node_modules/stylus/bin/stylus -u', + ' nib -w' . join(' ', $files) . ' -o assets/css/' + ); + $this->_exec(join(' ', $command)); +======= + $js_files = glob('assets/js/src/*.js'); + + $this->taskWatch() + ->monitor($js_files, function() { + $this->compileJavascript(); + }) + ->monitor($css_files, function() use($css_files) { + $this->compileStyles($css_files); + }) + ->run(); + } + + function compileJavascript() { + $this->_exec('./node_modules/webpack/bin/webpack.js'); + } + + protected function compileStyles($files = array()) { + if(empty($files)) { return; } + + $this->_exec(join(' ', array( + './node_modules/stylus/bin/stylus', + '-u nib', + '-w', + join(' ', $files), + '-o assets/css/' + ))); +>>>>>>> origin/master + } + + function makepot() { + $this->_exec('grunt makepot' . ' --gruntfile ' + . __DIR__ . '/tasks/makepot/makepot.js' + . ' --base_path ' . __DIR__); + } + + function pushpot() { + $this->_exec('grunt pushpot' . ' --gruntfile ' + . __DIR__ . '/tasks/makepot/makepot.js' + . ' --base_path ' . __DIR__); + } + + function testUnit() { + $this->loadEnv(); + $this->_exec('vendor/bin/codecept build'); + $this->_exec('vendor/bin/codecept run unit'); + } + + function testUnitSingle($unit = null) { + if (!$unit) { + throw new Exception("Your need to specify what you want to test (e.g.: test:unit-single models/SubscriberCest)"); + } + $this->loadEnv(); + $this->_exec('vendor/bin/codecept build'); + $this->_exec('vendor/bin/codecept run unit ' . $unit); + } + + function testAcceptance() { + $this->loadEnv(); + $this->_exec('vendor/bin/codecept build'); + $this->taskExec('phantomjs --webdriver=4444') + ->background() + ->run(); + sleep(2); + $this->_exec('vendor/bin/codecept run acceptance'); + } + + function testJavascript() { + $this->compileJavascript(); + + $this->_exec(join(' ', array( + './node_modules/mocha/bin/mocha', + '-r tests/javascript/mochaTestHelper.js', + 'tests/javascript/testBundles/**/*.js' + ))); + } + + function testAll() { + $this->loadEnv(); + $this->_exec('vendor/bin/codecept build'); + $this->taskexec('phantomjs --webdriver=4444') + ->background() + ->run(); + sleep(2); + $this->_exec('vendor/bin/codecept run'); + } + + function testDebug() { + $this->_exec('vendor/bin/codecept build'); + $this->loadEnv(); + $this->_exec('vendor/bin/codecept run unit --debug'); + } + + protected function loadEnv() { + $dotenv = new Dotenv\Dotenv(__DIR__); + $dotenv->load(); + + $this->taskWriteToFile('tests/acceptance.suite.yml') + ->textFromFile('tests/acceptance.suite.src') + ->run(); + + $this->taskReplaceInFile('tests/acceptance.suite.yml') + ->regex("/url.*/") + ->to('url: ' . "'" . getenv('WP_TEST_URL') . "'") + ->run(); + } +} diff --git a/lib/Config/Initializer.php b/lib/Config/Initializer.php index 94acae3ad4..1f32288910 100644 --- a/lib/Config/Initializer.php +++ b/lib/Config/Initializer.php @@ -1,15 +1,16 @@ '', + 'file' => '', 'version' => '1.0.0' )) { - Env::init($params['file'], $params['version']); + Env::init($params['file'], $params['version']); } function init() { @@ -27,9 +28,11 @@ class Initializer { $subscribers = Env::$db_prefix . 'subscribers'; $settings = Env::$db_prefix . 'settings'; + $newsletters = Env::$db_prefix . 'newsletters'; define('MP_SUBSCRIBERS_TABLE', $subscribers); define('MP_SETTINGS_TABLE', $settings); + define('MP_NEWSLETTERS_TABLE', $newsletters); } function setupActivator() { diff --git a/lib/Config/Migrator.php b/lib/Config/Migrator.php index 3e56a2a132..bdf7c0ed11 100644 --- a/lib/Config/Migrator.php +++ b/lib/Config/Migrator.php @@ -1,8 +1,7 @@ charset = Env::$db_charset; $this->models = array( 'subscribers', - 'settings' + 'settings', + 'newsletters' ); } function up() { global $wpdb; - $_this = $this; - $migrate = function($model) use ($_this) { + $_this = $this; + $migrate = function ($model) use ($_this) { dbDelta($_this->$model()); }; @@ -30,7 +30,7 @@ class Migrator { function down() { global $wpdb; - $drop_table = function($model) { + $drop_table = function ($model) { $table = $this->prefix . $model; $wpdb->query("DROP TABLE {$table}"); }; @@ -65,13 +65,25 @@ class Migrator { return $this->sqlify(__FUNCTION__, $attributes); } + function newsletters() { + $attributes = array( + 'id mediumint(9) NOT NULL AUTO_INCREMENT,', + 'subject varchar(250) NOT NULL,', + 'body longtext,', + 'created_at TIMESTAMP NOT NULL DEFAULT 0,', + 'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,', + 'PRIMARY KEY (id)' + ); + return $this->sqlify(__FUNCTION__, $attributes); + } + private function sqlify($model, $attributes) { $table = $this->prefix . $model; $sql = array(); $sql[] = "CREATE TABLE " . $table . " ("; $sql = array_merge($sql, $attributes); - $sql[] = ") " . $this->charset . ";"; + $sql[] = ") " . $this->charset . ";"; return implode("\n", $sql); } diff --git a/lib/Models/Newsletter.php b/lib/Models/Newsletter.php new file mode 100644 index 0000000000..ace405ab26 --- /dev/null +++ b/lib/Models/Newsletter.php @@ -0,0 +1,17 @@ +addValidations('subject', array( + 'required' => "subject_is_blank" + )); + $this->addValidations('body', array( + 'required' => "body_is_blank" + )); + } +} diff --git a/package.json b/package.json index b8efae0805..3d0c8da7dc 100644 --- a/package.json +++ b/package.json @@ -1,43 +1,43 @@ -{ - "private": true, - "scripts": { - "install": "napa" - }, - "napa": { - "sticky-kit": "leafo/sticky-kit.git", - "jquery-validation-engine": "posabsolute/jQuery-Validation-Engine.git", - "interact.js": "taye/interact.js.git" - }, - "dependencies": { - "backbone": "1.2.0", - "backbone.marionette": "2.4.2", - "backbone.radio": "0.9.0", - "backbone.supermodel": "1.2.0", - "c3": "~0.4.10", - "codemirror": "^5.5.0", - "d3": "~3.5.5", - "handlebars": "3.0.3", - "html2canvas": "latest", - "moment": "^2.10.3", - "papaparse": "4.1.1", - "select2": "3.5.1", - "spectrum-colorpicker": "^1.6.2", - "tinymce": "4.1.10", - "underscore": "1.8.3", - "napa": "^1.2.0" - }, - "devDependencies": { - "chai": "2.2.0", - "chai-jq": "0.0.8", - "grunt": "^0.4.5", - "jquery": "2.1.4", - "jsdom": "3.1.2", - "mocha": "2.2.1", - "nib": "latest", - "sinon": "1.14.1", - "sinon-chai": "2.7.0", - "stylus": "latest", - "swag": "~0.7.0", - "webpack": "1.11.0" - } -} +{ + "private": true, + "scripts": { + "install": "napa" + }, + "napa": { + "sticky-kit": "leafo/sticky-kit.git", + "jquery-validation-engine": "posabsolute/jQuery-Validation-Engine.git", + "interact.js": "taye/interact.js.git" + }, + "dependencies": { + "backbone": "1.2.0", + "backbone.marionette": "2.4.2", + "backbone.radio": "0.9.0", + "backbone.supermodel": "1.2.0", + "c3": "~0.4.10", + "codemirror": "^5.5.0", + "d3": "~3.5.5", + "handlebars": "3.0.3", + "html2canvas": "latest", + "moment": "^2.10.3", + "papaparse": "4.1.1", + "select2": "3.5.1", + "spectrum-colorpicker": "^1.6.2", + "tinymce": "4.1.10", + "underscore": "1.8.3", + "napa": "^1.2.0" + }, + "devDependencies": { + "chai": "2.2.0", + "chai-jq": "0.0.8", + "grunt": "^0.4.5", + "jquery": "2.1.4", + "jsdom": "3.1.2", + "mocha": "2.2.1", + "nib": "latest", + "sinon": "1.14.1", + "sinon-chai": "2.7.0", + "stylus": "latest", + "swag": "~0.7.0", + "webpack": "1.11.0" + } +} diff --git a/tests/_bootstrap.php b/tests/_bootstrap.php index c3d64c1534..e5b525c3d6 100644 --- a/tests/_bootstrap.php +++ b/tests/_bootstrap.php @@ -7,11 +7,12 @@ require_once(getenv('WP_TEST_PATH') . '/wp-load.php'); $console->writeln('Cleaning up database...'); $models = array( - "Subscriber", - "Setting" + "Subscriber", + "Setting", + "Newsletter" ); $destroy = function ($model) { Model::factory("\MailPoet\Models\\" . $model) - ->delete_many(); + ->delete_many(); }; array_map($destroy, $models); diff --git a/tests/unit/Models/NewsletterCest.php b/tests/unit/Models/NewsletterCest.php new file mode 100644 index 0000000000..ff11cc362c --- /dev/null +++ b/tests/unit/Models/NewsletterCest.php @@ -0,0 +1,75 @@ +before_time = time(); + $this->data = array( + 'subject' => 'My First Newsletter', + 'body' => 'a verrryyyyy long body :)' + ); + + $newsletter = Newsletter::create(); + $newsletter->hydrate($this->data); + $newsletter->save(); + } + + function itCanBeCreated() { + $newsletter = Newsletter::where('subject', $this->data['subject']) + ->findOne(); + expect($newsletter->id)->notNull(); + } + + function subjectShouldValidate() { + $conflict_newsletter = Newsletter::create(); + $conflict_newsletter->validateField('subject', ''); + expect($conflict_newsletter->getValidationErrors()[0])->equals('subject_is_blank'); + } + + function bodyShouldValidate() { + $conflict_newsletter = Newsletter::create(); + $conflict_newsletter->validateField('body', ''); + expect($conflict_newsletter->getValidationErrors()[0])->equals('body_is_blank'); + } + + function itHasACreatedAtOnCreation() { + $newsletter = Newsletter::where('subject', $this->data['subject']) + ->findOne(); + $time_difference = strtotime($newsletter->created_at) >= $this->before_time; + expect($time_difference)->equals(true); + } + + function itHasAnUpdatedAtOnCreation() { + $newsletter = Newsletter::where('subject', $this->data['subject']) + ->findOne(); + $time_difference = strtotime($newsletter->updated_at) >= $this->before_time; + expect($time_difference)->equals(true); + } + + function itKeepsTheCreatedAtOnUpdate() { + $newsletter = Newsletter::where('subject', $this->data['subject']) + ->findOne(); + $old_created_at = $newsletter->created_at; + $newsletter->subject = $this->data['subject']; + $newsletter->save(); + expect($old_created_at)->equals($newsletter->created_at); + } + + function itUpdatesTheUpdatedAtOnUpdate() { + $newsletter = Newsletter::where('subject', $this->data['subject']) + ->findOne(); + $update_time = time(); + $newsletter->subject = $this->data['subject']; + $newsletter->save(); + $time_difference = strtotime($newsletter->updated_at) >= $update_time; + expect($time_difference)->equals(true); + } + + function _after() { + $newsletter = Newsletter::where('subject', $this->data['subject']) + ->findOne() + ->delete(); + } +} diff --git a/tests/unit/Models/SettingCest.php b/tests/unit/Models/SettingCest.php index b51954dbfa..46809a222d 100644 --- a/tests/unit/Models/SettingCest.php +++ b/tests/unit/Models/SettingCest.php @@ -2,7 +2,7 @@ use MailPoet\Models\Setting; class SettingCest { - + function _before() { $this->before_time = time(); $this->data = array( @@ -16,7 +16,8 @@ class SettingCest { } function itCanBeCreated() { - $setting = Setting::where('name', $this->data['name'])->findOne(); + $setting = Setting::where('name', $this->data['name']) + ->findOne(); expect($setting->id)->notNull(); } @@ -49,19 +50,22 @@ class SettingCest { } function itHasACreatedAtOnCreation() { - $setting = Setting::where('name', 'sending_method')->findOne(); + $setting = Setting::where('name', $this->data['name']) + ->findOne(); $time_difference = strtotime($setting->created_at) >= $this->before_time; expect($time_difference)->equals(true); } function itHasAnUpdatedAtOnCreation() { - $setting = Setting::where('name', 'sending_method')->findOne(); + $setting = Setting::where('name', $this->data['name']) + ->findOne(); $time_difference = strtotime($setting->updated_at) >= $this->before_time; expect($time_difference)->equals(true); } function itKeepsTheCreatedAtOnUpdate() { - $setting = Setting::where('name', 'sending_method')->findOne(); + $setting = Setting::where('name', $this->data['name']) + ->findOne(); $old_created_at = $setting->created_at; $setting->value = 'http_api'; $setting->save(); @@ -69,15 +73,18 @@ class SettingCest { } function itUpdatesTheUpdatedAtOnUpdate() { - $setting = Setting::where('name', 'sending_method')->findOne(); + $setting = Setting::where('name', $this->data['name']) + ->findOne(); $update_time = time(); $setting->value = 'http_api'; $setting->save(); $time_difference = strtotime($setting->updated_at) >= $update_time; expect($time_difference)->equals(true); } - + function _after() { - $setting = Setting::where('name', $this->data['name'])->findOne()->delete(); + $setting = Setting::where('name', $this->data['name']) + ->findOne() + ->delete(); } } diff --git a/tests/unit/Models/SubscriberCest.php b/tests/unit/Models/SubscriberCest.php index f9d3a2f536..2e11f39f02 100644 --- a/tests/unit/Models/SubscriberCest.php +++ b/tests/unit/Models/SubscriberCest.php @@ -17,22 +17,26 @@ class SubscriberCest { } function itCanBeCreated() { - $subscriber = Subscriber::where('email', $this->data['email'])->findOne(); + $subscriber = Subscriber::where('email', $this->data['email']) + ->findOne(); expect($subscriber->id)->notNull(); } function itHasAFirstName() { - $subscriber = Subscriber::where('email', $this->data['email'])->findOne(); + $subscriber = Subscriber::where('email', $this->data['email']) + ->findOne(); expect($subscriber->first_name)->equals($this->data['first_name']); } function itHasALastName() { - $subscriber = Subscriber::where('email', $this->data['email'])->findOne(); + $subscriber = Subscriber::where('email', $this->data['email']) + ->findOne(); expect($subscriber->last_name)->equals($this->data['last_name']); } function itHasAnEmail() { - $subscriber = Subscriber::where('email', $this->data['email'])->findOne(); + $subscriber = Subscriber::where('email', $this->data['email']) + ->findOne(); expect($subscriber->email)->equals($this->data['email']); } @@ -81,21 +85,21 @@ class SubscriberCest { function itHasACreatedAtOnCreation() { $subscriber = Subscriber::where('email', $this->data['email']) - ->findOne(); + ->findOne(); $time_difference = strtotime($subscriber->created_at) >= $this->before_time; expect($time_difference)->equals(true); } function itHasAnUpdatedAtOnCreation() { $subscriber = Subscriber::where('email', $this->data['email']) - ->findOne(); + ->findOne(); $time_difference = strtotime($subscriber->updated_at) >= $this->before_time; expect($time_difference)->equals(true); } function itKeepsTheCreatedAtOnUpdate() { $subscriber = Subscriber::where('email', $this->data['email']) - ->findOne(); + ->findOne(); $old_created_at = $subscriber->created_at; @@ -106,7 +110,8 @@ class SubscriberCest { } function itUpdatesTheUpdatedAtOnUpdate() { - $subscriber = Subscriber::where('email', $this->data['email'])->findOne(); + $subscriber = Subscriber::where('email', $this->data['email']) + ->findOne(); $update_time = time(); $subscriber->first_name = 'New Name'; @@ -118,7 +123,9 @@ class SubscriberCest { } function _after() { - $subscriber = Subscriber::where('email', $this->data['email'])->findOne()->delete(); + $subscriber = Subscriber::where('email', $this->data['email']) + ->findOne() + ->delete(); } }