diff --git a/.travis.yml b/.travis.yml index d11bd20..39ec022 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,29 +1,67 @@ -language: php - -notifications: - email: - on_success: never - on_failure: change +sudo: false -branches: - only: - - master +language: php -php: - - 5.3 - - 5.6 +git: + depth: 1 -env: - - WP_VERSION=latest WP_MULTISITE=0 - - WP_VERSION=3.7 WP_MULTISITE=0 - - WP_VERSION=4.7-alpha-38178-src WP_MULTISITE=0 +notifications: + email: false matrix: + # - Lint PHP once per PHP version. + # + # - Run `phpunit` for each version of PHP and WordPress in single- and multisite. + # + # - Run `qunit:recent` once. The `recent` task handles running tests against + # different versions of WordPress. If we switch to WP_VERSION=x.y.z we could + # instead run `qunit:specific --wp=$WP_VERSION` so that control over which + # versions are tested stays in this config. include: - php: 5.3 - env: WP_VERSION=latest WP_MULTISITE=1 + env: WP_VERSION=latest PHP_LINT=1 + + - php: 5.6 + env: WP_VERSION=latest PHP_LINT=1 + + - php: 7.0 + env: WP_VERSION=trunk QUNIT_RECENT=1 + - php: 7.0 + env: WP_VERSION=latest PHP_LINT=1 + + - php: 7.1 + env: WP_VERSION=latest PHP_LINT=1 before_script: + - export PATH="$HOME/.composer/vendor/bin:$PATH" + - export WP_CORE_DIR=/tmp/wordpress + + - | + if [[ ${TRAVIS_PHP_VERSION:0:2} == "7." ]]; then + composer global require "phpunit/phpunit=5.7.*" + else + composer global require "phpunit/phpunit=4.8.*" + fi + - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION -script: phpunit + - git clone --depth=1 https://github.com/alleyinteractive/wordpress-fieldmanager $WP_CORE_DIR/wp-content/plugins/wordpress-fieldmanager + + - | + if [[ "$QUNIT_RECENT" == "1" ]]; then + npm install + fi + +script: + - | + if [[ "$PHP_LINT" == "1" ]]; then + find . -type "f" -iname "*.php" | xargs -L "1" php -l + fi + + - | + if [[ "$QUNIT_RECENT" == "1" ]]; then + grunt qunit:recent + fi + + - export WP_MULTISITE=0 && phpunit + - export WP_MULTISITE=1 && phpunit diff --git a/Gruntfile.js b/Gruntfile.js index b16448a..ef15c70 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,10 +1,10 @@ module.exports = function( grunt ) { - 'use strict'; + var banner = '/**\n * <%= pkg.homepage %>\n * Copyright (c) <%= grunt.template.today("yyyy") %>\n * This file is generated automatically. Do not edit.\n */\n'; + // Project configuration grunt.initConfig( { - pkg: grunt.file.readJSON( 'package.json' ), addtextdomain: { @@ -18,15 +18,12 @@ module.exports = function( grunt ) { } }, - wp_readme_to_markdown: { - options: { - screenshot_url: './assets/{screenshot}.png', - }, - your_target: { - files: { - 'README.md': 'readme.txt' + connect: { + server: { + options: { + base: '.' } - }, + } }, makepot: { @@ -44,14 +41,53 @@ module.exports = function( grunt ) { } } }, + + qunit: { + trunk: { + options: { + urls: ['http://localhost:8000/tests/js/index.html'] + } + }, + recent: { + options: { + urls: [ + 'http://localhost:8000/tests/js/index.html', + 'http://localhost:8000/tests/js/index.html?wp=4.7', + 'http://localhost:8000/tests/js/index.html?wp=4.6', + ] + } + }, + specific: { + options: { + urls: [ 'http://localhost:8000/tests/js/index.html?wp=' + grunt.option( 'wp' ) ] + } + } + }, + + wp_readme_to_markdown: { + options: { + screenshot_url: './assets/{screenshot}.png', + }, + your_target: { + files: { + 'README.md': 'readme.txt' + } + }, + }, } ); + grunt.loadNpmTasks( 'grunt-contrib-connect' ); + grunt.loadNpmTasks( 'grunt-contrib-qunit' ); grunt.loadNpmTasks( 'grunt-wp-i18n' ); grunt.loadNpmTasks( 'grunt-wp-readme-to-markdown' ); + + if ( /(qunit|prerelease)/.test( grunt.cli.tasks.join( '' ).toLowerCase() ) ) { + grunt.task.run( 'connect' ); + } + grunt.registerTask( 'i18n', [ 'addtextdomain', 'makepot' ] ); grunt.registerTask( 'readme', [ 'wp_readme_to_markdown' ] ); - grunt.registerTask( 'prerelease', [ 'i18n', 'readme' ] ); + grunt.registerTask( 'prerelease', [ 'qunit:recent', 'i18n', 'readme' ] ); grunt.util.linefeed = '\n'; - }; diff --git a/README.md b/README.md index e2a3b0b..de392b7 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Fieldmanager Beta: Customize # **Contributors:** [dlh](https://profiles.wordpress.org/dlh), [jamesburke](https://profiles.wordpress.org/jamesburke), [alleyinteractive](https://profiles.wordpress.org/alleyinteractive) -**Requires at least:** 4.4 +**Requires at least:** 4.5 **Tested up to:** 4.7 -**Stable tag:** 0.3.1 +**Stable tag:** 0.4.0 **License:** GPLv2 or later **License URI:** http://www.gnu.org/licenses/gpl-2.0.html @@ -12,7 +12,7 @@ A Fieldmanager Beta plugin for the Customize Context. This is a proposed Customize context for Fieldmanager. You can install the plugin alongside a stable Fieldmanager release to help test and refine the context. -The official Pull Request for this context, plus tests, is [on GitHub](https://github.com/alleyinteractive/wordpress-fieldmanager/pull/399). +The official Pull Request for this context is [on GitHub](https://github.com/alleyinteractive/wordpress-fieldmanager/pull/399). ## Installation ## @@ -41,6 +41,13 @@ For more code examples, browse `php/demos/class-fieldmanager-beta-customize-demo ## Changelog ## +### 0.4.0 ### +* Added: PHP and JavaScript tests. +* Added: Demo a field with selective-refresh support. +* Changed: Use better TinyMCE events for tracking `Fieldmanager_RichTextArea` changes. +* Changed: Require at least WordPress 4.5. +* Fixed: Fix a case where invisible Customizer sections could be created. + ### 0.3.1 ### * Fixed: Track the changes to instances of repeatable RichTextAreas and Colorpickers added after loading the Customizer. diff --git a/bin/install-wp-tests.sh b/bin/install-wp-tests.sh index cf709c2..73bb4c7 100755 --- a/bin/install-wp-tests.sh +++ b/bin/install-wp-tests.sh @@ -80,6 +80,7 @@ install_test_suite() { # set up testing suite mkdir -p $WP_TESTS_DIR svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes + svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/data/ $WP_TESTS_DIR/data fi if [ ! -f wp-tests-config.php ]; then diff --git a/fieldmanager-beta-customize.php b/fieldmanager-beta-customize.php index 5f6ae55..f0624cf 100755 --- a/fieldmanager-beta-customize.php +++ b/fieldmanager-beta-customize.php @@ -7,7 +7,7 @@ * Author URI: https://www.alleyinteractive.com * Text Domain: fieldmanager-beta-customizer * Domain Path: /languages - * Version: 0.3.1 + * Version: 0.4.0 * * @package Fieldmanager_Beta_Customize */ @@ -25,7 +25,19 @@ /** * Plugin version. */ -define( 'FM_BETA_CUSTOMIZE_VERSION', '0.3.1' ); +define( 'FM_BETA_CUSTOMIZE_VERSION', '0.4.0' ); + +/** + * Load plugin class files. + * + * @since 0.4.0 + */ +function fm_beta_customize_load_plugin_classes() { + require_once( FM_BETA_CUSTOMIZE_PATH . 'php/context/class-fieldmanager-beta-context-customize.php' ); + require_once( FM_BETA_CUSTOMIZE_PATH . 'php/customize/class-fieldmanager-beta-customize-control.php' ); + require_once( FM_BETA_CUSTOMIZE_PATH . 'php/customize/class-fieldmanager-beta-customize-setting.php' ); + require_once( FM_BETA_CUSTOMIZE_PATH . 'php/field/class-fieldmanager-beta-customize-richtextarea.php' ); +} /** * Calculate a Fieldmanager context for the Customizer. @@ -50,13 +62,7 @@ * We aren't registering an autoloader because if Fieldmanager core's autoloader * is registered first, and it doesn't find a file, it throws an exception. */ -add_action( 'fm_beta_customize', function () { - require_once( FM_BETA_CUSTOMIZE_PATH . 'php/context/class-fieldmanager-beta-context-customize.php' ); - require_once( FM_BETA_CUSTOMIZE_PATH . 'php/customize/class-fieldmanager-beta-customize-control.php' ); - require_once( FM_BETA_CUSTOMIZE_PATH . 'php/customize/class-fieldmanager-beta-customize-setting.php' ); - require_once( FM_BETA_CUSTOMIZE_PATH . 'php/demo/class-fieldmanager-beta-customize-demo.php' ); - require_once( FM_BETA_CUSTOMIZE_PATH . 'php/field/class-fieldmanager-beta-customize-richtextarea.php' ); -}, 0 ); +add_action( 'fm_beta_customize', 'fm_beta_customize_load_plugin_classes', 0 ); /** * Enqueue assets managed by Fieldmanager_Util_Assets in the Customizer. @@ -130,5 +136,6 @@ function fm_beta_customize_add_to_customizer( $args = array(), $fm ) { * Instantiate the bundled context demos. */ function fm_beta_customize_demo() { + require_once( FM_BETA_CUSTOMIZE_PATH . 'php/demo/class-fieldmanager-beta-customize-demo.php' ); Fieldmanager_Beta_Customize_Demo::instance(); } diff --git a/js/fieldmanager-beta-customize-overrides.js b/js/fieldmanager-beta-customize-overrides.js index 0df7758..00142d5 100644 --- a/js/fieldmanager-beta-customize-overrides.js +++ b/js/fieldmanager-beta-customize-overrides.js @@ -70,12 +70,12 @@ // Respond to RichTextArea changes. $( document ).on( 'tinymce-editor-init', function ( event, editor ) { - var editor_element = document.getElementById( editor.id ); + var editorElement = document.getElementById( editor.id ); - if ( editor_element && editor_element.classList.contains( 'fm-richtext' ) ) { - editor.on( 'keyup AddUndo SetContent', function () { + if ( editorElement && editorElement.classList.contains( 'fm-richtext' ) ) { + editor.on( 'input change keyup', function () { editor.save(); - fm.beta.customize.setControlsContainingElement( editor_element ); + fm.beta.customize.setControlsContainingElement( editorElement ); }); } }); diff --git a/js/fieldmanager-beta-customize.js b/js/fieldmanager-beta-customize.js index fd5e78d..da71e3d 100644 --- a/js/fieldmanager-beta-customize.js +++ b/js/fieldmanager-beta-customize.js @@ -49,6 +49,14 @@ /** * Set a Fieldmanager setting to its control's form values. * + * Updates to fields are generally not debounced or throttled because + * these create FM-specific deviations to how users experience the + * Customizer and add maintenance requirements for the plugin. + * + * Without debouncing or throttling, changes to settings using the + * `postMessage` transport are faster. The Customizer's refresh + * framework also debounces natively. + * * @param {Object} control Customizer Control object. * @return {Object} The updated Control. */ diff --git a/languages/fieldmanager-beta-customize.pot b/languages/fieldmanager-beta-customize.pot index 78b8d25..4fb66cb 100644 --- a/languages/fieldmanager-beta-customize.pot +++ b/languages/fieldmanager-beta-customize.pot @@ -2,10 +2,10 @@ # This file is distributed under the same license as the Fieldmanager Beta: Customize package. msgid "" msgstr "" -"Project-Id-Version: Fieldmanager Beta: Customize 0.3.1\n" +"Project-Id-Version: Fieldmanager Beta: Customize 0.4.0\n" "Report-Msgid-Bugs-To: " "https://wordpress.org/support/plugin/fieldmanager-beta-customize\n" -"POT-Creation-Date: 2017-01-22 00:22:27+00:00\n" +"POT-Creation-Date: 2017-03-23 03:56:54+00:00\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -25,7 +25,7 @@ msgstr "" "X-Poedit-Bookmarks: \n" "X-Textdomain-Support: yes\n" -#: php/context/class-fieldmanager-beta-context-customize.php:90 +#: php/context/class-fieldmanager-beta-context-customize.php:89 msgid "Invalid value." msgstr "" @@ -41,22 +41,30 @@ msgid "" "Fieldmanager_Beta_Context_Customize" msgstr "" -#: php/demo/class-fieldmanager-beta-customize-demo.php:87 +#: php/demo/class-fieldmanager-beta-customize-demo.php:116 msgid "Twitter Handle" msgstr "" -#: php/demo/class-fieldmanager-beta-customize-demo.php:88 +#: php/demo/class-fieldmanager-beta-customize-demo.php:117 msgid "Facebook URL" msgstr "" -#: php/demo/class-fieldmanager-beta-customize-demo.php:89 +#: php/demo/class-fieldmanager-beta-customize-demo.php:118 msgid "Instagram Handle" msgstr "" -#: php/demo/class-fieldmanager-beta-customize-demo.php:90 +#: php/demo/class-fieldmanager-beta-customize-demo.php:119 msgid "YouTube URL" msgstr "" +#: tests/php/test-fieldmanager-beta-context-customize.php:189 +msgid "Failed with $debug = true" +msgstr "" + +#: tests/php/test-fieldmanager-beta-context-customize.php:189 +msgid "Failed with $debug = false" +msgstr "" + #. Plugin Name of the plugin/theme msgid "Fieldmanager Beta: Customize" msgstr "" diff --git a/package.json b/package.json index f6e03ac..0d64ab7 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fieldmanager-beta-customize", - "version": "0.1.0", + "version": "0.4.0", "main": "Gruntfile.js", "contributors": [ "David Herrera", @@ -8,8 +8,11 @@ "Alley Interactive" ], "devDependencies": { - "grunt": "~0.4.5", + "grunt": "~1.0.0", + "grunt-contrib-connect": "~1.0.0", + "grunt-contrib-qunit": "~1.3.0", "grunt-wp-i18n": "~0.5.0", - "grunt-wp-readme-to-markdown": "~2.0.0" + "grunt-wp-readme-to-markdown": "~2.0.0", + "qunitjs": "^2.1.1" } } diff --git a/php/context/class-fieldmanager-beta-context-customize.php b/php/context/class-fieldmanager-beta-context-customize.php index 4353e94..9b17330 100644 --- a/php/context/class-fieldmanager-beta-context-customize.php +++ b/php/context/class-fieldmanager-beta-context-customize.php @@ -13,8 +13,7 @@ class Fieldmanager_Beta_Context_Customize extends Fieldmanager_Context { * Arguments to construct Customizer objects. * * @var array $args { - * @type array|bool $section_args Arguments for constructing a {@see WP_Customize_Section}, - * or false to not create one for this context. + * @type array $section_args Arguments for constructing a {@see WP_Customize_Section}. * @type array $setting_args Arguments for constructing a {@see Fieldmanager_Beta_Customize_Setting}. * @type array $control_args Arguments for constructing a {@see Fieldmanager_Beta_Customize_Control}. * } @@ -29,7 +28,7 @@ class Fieldmanager_Beta_Context_Customize extends Fieldmanager_Context { */ public function __construct( $args, $fm ) { $this->args = wp_parse_args( $args, array( - 'section_args' => false, + 'section_args' => array(), 'setting_args' => array(), 'control_args' => array(), ) ); @@ -187,11 +186,14 @@ protected function register( $manager ) { /** * Add a Customizer section for this field. * + * @since 0.4.0 Does not create a section when the context's $args['section_args'] is an + * empty array. In practice, a Customizer section requires at least a title. + * * @param WP_Customize_Manager $manager WP_Customize_Manager instance. * @return WP_Customize_Section|void Section object, where supported, if created. */ protected function register_section( $manager ) { - if ( false === $this->args['section_args'] ) { + if ( ! $this->args['section_args'] ) { return; } diff --git a/php/demo/class-fieldmanager-beta-customize-demo.php b/php/demo/class-fieldmanager-beta-customize-demo.php index 6458717..d262381 100644 --- a/php/demo/class-fieldmanager-beta-customize-demo.php +++ b/php/demo/class-fieldmanager-beta-customize-demo.php @@ -33,21 +33,50 @@ public static function instance() { * Set up. */ public function setup() { + add_action( 'customize_register', array( $this, 'add_partial' ) ); add_action( 'fm_beta_customize', array( $this, 'customizer_init' ), 1000 ); } + /** + * Register a demo selective-refresh partial. + */ + public function add_partial( $wp_customize ) { + if ( empty( $wp_customize->selective_refresh ) ) { + return; + } + + $wp_customize->selective_refresh->add_partial( 'basic_partial', array( + 'selector' => '#fm-demo-customizer-basic-partial', + 'settings' => array( 'basic_partial' ), + 'render_callback' => array( $this, 'get_basic_partial' ), + ) ); + } + + /** + * Render callback for basic_partial. + */ + public function get_basic_partial() { + return get_option( 'basic_partial' ); + } + /** * Initialize demos. */ public function customizer_init() { - $fm = new Fieldmanager_Textfield( array( 'name' => 'basic_text' ) ); + $fm = new Fieldmanager_Textfield( 'Text Field', array( 'name' => 'basic_text' ) ); fm_beta_customize_add_to_customizer( array( 'section_args' => array( 'priority' => 10, - 'title' => 'Fieldmanager Text Field', + 'title' => 'Fieldmanager Text Fields', ), ), $fm ); + $fm = new Fieldmanager_TextField( 'Text Field with Selective Refresh', array( 'name' => 'basic_partial' ) ); + fm_beta_customize_add_to_customizer( array( + 'control_args' => array( 'section' => 'basic_text' ), + 'setting_args' => array( 'transport' => 'postMessage' ), + ), $fm ); + $fm = new Fieldmanager_Group( array( 'name' => 'option_fields', 'children' => array( @@ -185,6 +214,11 @@ public function wp_footer() {
The values you see below are controlled by "Fieldmanager Text Field" and "Fieldmanager Group" sections in the Customizer. Try changing them to see the results.
Proin mi arcu, porttitor vel tellus vel, lobortis suscipit risus. Quisque consectetur eu arcu in commodo.
+', + ), + ), + ), + ); + + $context = new Fieldmanager_Beta_Context_Customize( 'Foo', $fm ); + $this->register(); + $setting = $this->manager->get_setting( $fm->name ); + + $this->assertSame( $expected, $context->sanitize_callback( $in_as_json, $setting ) ); + $this->assertSame( $expected, $context->sanitize_callback( $in_as_serialized, $setting ) ); + } + + // Make sure sanitizing strips slashes. + function test_sanitize_stripslashes() { + $context = new Fieldmanager_Beta_Context_Customize( 'Foo', $this->field ); + $this->register(); + $this->assertSame( 'Foo "bar" baz', $context->sanitize_callback( 'Foo \"bar\" baz', $this->manager->get_setting( $this->field->name ) ) ); + } + + /** + * Make sure sanitizing returns a WP_Error on an invalid value. + * + * @dataProvider data_field_debug + */ + function test_sanitize_invalid_value( $debug ) { + global $wp_actions; + + Fieldmanager_Field::$debug = $debug; + $this->field->validate = array( 'is_numeric' ); + + $context = new Fieldmanager_Beta_Context_Customize( 'Foo', $this->field ); + $this->register(); + do_action( 'customize_save_validation_before' ); + + $this->assertWPError( $context->sanitize_callback( rand_str(), $this->manager->get_setting( $this->field->name ) ) ); + + // "Revert" to not affect future did_action() checks. + $wp_actions['customize_save_validation_before']--; + } + + /** + * Make sure sanitizing returns null on an invalid value where we don't have Customizer validation. + * + * @dataProvider data_field_debug + */ + function test_sanitize_invalid_value_backcompat( $debug ) { + Fieldmanager_Field::$debug = $debug; + $this->field->validate = array( 'is_numeric' ); + + $context = new Fieldmanager_Beta_Context_Customize( 'Foo', $this->field ); + $this->register(); + + $this->assertNull( $context->sanitize_callback( rand_str(), $this->manager->get_setting( $this->field->name ) ) ); + } + + // Make sure the context's rendering method calls the field rendering method. + function test_render_field() { + $field = $this->getMockBuilder( 'Fieldmanager_Textfield' )->disableOriginalConstructor()->getMock(); + $context = new Fieldmanager_Beta_Context_Customize( 'Foo', $field ); + + $field->expects( $this->once() )->method( 'element_markup' ); + $context->render_field( array( 'echo' => false ) ); + } +} diff --git a/tests/php/test-fieldmanager-beta-customize-control.php b/tests/php/test-fieldmanager-beta-customize-control.php new file mode 100644 index 0000000..5c212d6 --- /dev/null +++ b/tests/php/test-fieldmanager-beta-customize-control.php @@ -0,0 +1,73 @@ +mock_context = $this->getMockBuilder( 'Fieldmanager_Beta_Context_Customize' ) + ->disableOriginalConstructor() + ->getMock(); + } + + function test_parent_construction() { + $priority = 99; + + $actual = new Fieldmanager_Beta_Customize_Control( $this->manager, 'foo', array( + 'context' => $this->mock_context, + 'priority' => $priority, + ) ); + + $this->assertSame( $priority, $actual->priority ); + } + + /** + * @expectedException FM_Developer_Exception + */ + function test_invalid_construction() { + new Fieldmanager_Beta_Customize_Control( $this->manager, 'foo', array() ); + } + + function test_type() { + $control = new Fieldmanager_Beta_Customize_Control( $this->manager, rand_str(), array( 'context' => $this->mock_context ) ); + $this->assertSame( 'fieldmanager-beta', $control->type ); + } + + /** + * Tests for scripts registered with wp_register_script(). + */ + function test_register_scripts() { + $before = wp_scripts()->registered; + + $control = new Fieldmanager_Beta_Customize_Control( $this->manager, rand_str(), array( 'context' => $this->mock_context ) ); + $control->enqueue(); + + $after = wp_scripts()->registered; + $this->assertSame( 1, ( count( $after ) - count( $before ) ) ); + } + + function test_render_content() { + $name = rand_str(); + $value = rand_str(); + $label = rand_str(); + $description = rand_str(); + + $context = new Fieldmanager_Beta_Context_Customize( array( + // Bypass capability checks. + 'section_args' => array( 'capability' => 'exist' ), + 'setting_args' => array( 'capability' => 'exist' ), + 'control_args' => array( 'label' => $label, 'description' => $description ), + ), new Fieldmanager_Textfield( array( 'name' => $name ) ) ); + + update_option( $name, $value ); + $this->register(); + + $actual = $this->manager->get_control( $name )->get_content(); + $this->assertContains( 'fm-element', $actual ); + $this->assertContains( sprintf( 'name="%s"', $name ), $actual ); + $this->assertRegExp( '#<([^ ]+)[^>]*?>' . $label . '\1>#', $actual ); + $this->assertRegExp( '#<([^ ]+)[^>]*?>' . $description . '\1>#', $actual ); + // Slip in a test that the option value is also used. + $this->assertContains( sprintf( 'value="%s"', $value ), $actual ); + } +} diff --git a/tests/php/test-fieldmanager-beta-customize-setting.php b/tests/php/test-fieldmanager-beta-customize-setting.php new file mode 100644 index 0000000..b7915dd --- /dev/null +++ b/tests/php/test-fieldmanager-beta-customize-setting.php @@ -0,0 +1,80 @@ +field = new Fieldmanager_TextField( array( 'name' => 'foo' ) ); + $this->context = new Fieldmanager_Beta_Context_Customize( array(), $this->field ); + } + + function test_construction() { + $actual = new Fieldmanager_Beta_Customize_Setting( $this->manager, $this->field->name, array( + 'context' => $this->context, + ) ); + + $this->assertInstanceOf( 'Fieldmanager_Beta_Customize_Setting', $actual ); + $this->assertSame( $this->field->default_value, $actual->default ); + $this->assertSame( array( $this->context, 'sanitize_callback' ), $actual->sanitize_callback ); + $this->assertSame( 'option', $actual->type ); + } + + /** + * Test that properties set by default by Fieldmanager_Beta_Customize_Setting can be overridden. + */ + function test_parent_construction() { + $actual = new Fieldmanager_Beta_Customize_Setting( $this->manager, $this->field->name, array( + 'context' => $this->context, + 'default' => 123456, + 'sanitize_callback' => 'absint', + 'type' => 'bar', + ) ); + + $this->assertInstanceOf( 'Fieldmanager_Beta_Customize_Setting', $actual ); + $this->assertSame( 123456, $actual->default ); + $this->assertSame( 'absint', $actual->sanitize_callback ); + $this->assertSame( 'bar', $actual->type ); + } + + /** + * @expectedException FM_Developer_Exception + */ + function test_invalid_construction() { + new Fieldmanager_Beta_Customize_Setting( $this->manager, $this->field->name, array() ); + } + + function test_preview_filter() { + global $wp_current_filter; + $_current_filter = $wp_current_filter; + + $original = rand_str(); + $preview = rand_str(); + + update_option( $this->field->name, $original ); + + /* + * Spoof a POSTed value so the manager thinks this is a preview. + * + * As of 4.7, $_POST is ignored unless the current user can 'customize'. + */ + $this->manager->set_post_value( $this->field->name, $preview ); + $this->let_all_users_customize(); + + $setting = new Fieldmanager_Beta_Customize_Setting( $this->manager, $this->field->name, array( + 'context' => $this->context, + ) ); + + // Verify the preview filter was added. + $this->assertNotFalse( $setting->preview() ); + // Verify that the option value is filtered to return the previewed value. + $this->assertSame( $preview, $setting->_preview_filter( $original ) ); + + // Spoof the current filter. + $wp_current_filter = array( "customize_sanitize_{$this->field->name}" ); + + // Verify that the option value is not filtered with the previewed value. + $this->assertSame( $original, $setting->_preview_filter( $original ) ); + + $wp_current_filter = $_current_filter; + } +} diff --git a/tests/php/testcase/class-fieldmanager-beta-customize-unittestcase.php b/tests/php/testcase/class-fieldmanager-beta-customize-unittestcase.php new file mode 100644 index 0000000..18bf254 --- /dev/null +++ b/tests/php/testcase/class-fieldmanager-beta-customize-unittestcase.php @@ -0,0 +1,39 @@ +manager = new WP_Customize_Manager(); + } + + public function register() { + do_action( 'customize_register', $this->manager ); + } + + /** + * Filters 'map_meta_cap' to map the 'customize' capability to 'exist'. + * + * @param array $caps Required primitive capabilities. + * @param string $cap Meta capability. + * @return array Updated required capabilities. + */ + public function map_customize_meta_cap_to_exist( $caps, $cap ) { + if ( 'customize' === $cap ) { + $caps = array( 'exist' ); + } + + return $caps; + } + + /** + * Add hooks to grant all users the capabilities to use the Customizer. + * + * @return bool Whether the hooks were successfully added. + */ + protected function let_all_users_customize() { + return ( + add_filter( 'map_meta_cap', array( $this, 'map_customize_meta_cap_to_exist' ), 10, 2 ) + ); + } +}