2024-08-13

This commit is contained in:
gcch 2024-08-13 15:28:49 +02:00
commit 6b27b6d5e6
30 changed files with 6781 additions and 2 deletions

View file

@ -0,0 +1,9 @@
/tests export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.scrutinizer.yml export-ignore
.travis.yml export-ignore
DEVELOPMENT.md export-ignore
phpcs.xml export-ignore
phpunit.xml export-ignore
Vagrantfile export-ignore

View file

@ -0,0 +1,34 @@
# Editors
project.xml
project.properties
/nbproject/private/
.buildpath
.project
.settings*
sftp-config.json
.idea
# OS X metadata
.DS_Store
# Windows thumbnail cache
Thumbs.db
# Node
node_modules
# Unit tests
/tmp
# Composer
/vendor
composer.lock
# Vagrant
.vagrant
# Bundled assets
/assets/dist/
carbon-fields.zip
package-lock.json

View file

@ -0,0 +1,74 @@
filter:
excluded_paths:
- core/Pimple/*
- assets/*
- languages/*
- tests/*
- templates/*
- tmp/*
- vendor/*
checks:
php:
verify_argument_usable_as_reference: false
verify_property_names: false
no_global_keyword: false
psr2_class_declaration: false
avoid_superglobals: false
one_class_per_file: false
code_rating: true
coding_standard:
name: WordPress
tools:
sensiolabs_security_checker: true
external_code_coverage: true
php_mess_detector:
config:
code_size_rules: { cyclomatic_complexity: true, npath_complexity: true, excessive_method_length: true, excessive_class_length: true, excessive_parameter_list: true, excessive_public_count: true, too_many_fields: true, too_many_methods: true, excessive_class_complexity: true }
design_rules: { number_of_class_children: true, depth_of_inheritance: true, coupling_between_objects: true }
unused_code_rules: { unused_local_variable: true, unused_private_method: true, unused_formal_parameter: true }
naming_rules: { short_variable: true, long_variable: true, short_method: true, boolean_method_name: true }
controversial_rules: { camel_case_class_name: true, camel_case_property_name: true, camel_case_method_name: true, camel_case_parameter_name: true, camel_case_variable_name: true }
php_cs_fixer:
config:
level: all
fixers: { unused_use: true, phpdoc_params: true, braces: true, php_closing_tag: true }
php_analyzer:
config:
suspicious_code: { enabled: true, overriding_parameter: true, overriding_closure_use: true, parameter_closure_use_conflict: true, parameter_multiple_times: true, non_existent_class_in_instanceof_check: true, non_existent_class_in_catch_clause: true, assignment_of_null_return: true, non_commented_switch_fallthrough: true, non_commented_empty_catch_block: true, overriding_private_members: true, use_statement_alias_conflict: true, precedence_in_condition_assignment: true }
verify_php_doc_comments: { enabled: true, parameters: true, return: true, suggest_more_specific_types: true, ask_for_return_if_not_inferrable: true, ask_for_param_type_annotation: true }
loops_must_use_braces: { enabled: true }
simplify_boolean_return: { enabled: true }
phpunit_checks: { enabled: true }
reflection_fixes: { enabled: true }
use_statement_fixes: { enabled: true, order_alphabetically: true, remove_unused: true, preserve_multiple: false, preserve_blanklines: false }
parameter_reference_check: { enabled: false }
checkstyle: { enabled: false, no_trailing_whitespace: true, naming: { enabled: true, local_variable: '^[a-z][a-zA-Z0-9]*$', abstract_class_name: ^Abstract|Factory$, utility_class_name: 'Utils?$', constant_name: '^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$', property_name: '^[a-z][a-zA-Z0-9]*$', method_name: '^(?:[a-z]|__)[a-zA-Z0-9]*$', parameter_name: '^[a-z][a-zA-Z0-9]*$', interface_name: '^[A-Z][a-zA-Z0-9]*Interface$', type_name: '^[A-Z][a-zA-Z0-9]*$', exception_name: '^[A-Z][a-zA-Z0-9]*Exception$', isser_method_name: '^(?:is|has|should|may|supports)' } }
unreachable_code: { enabled: false }
check_access_control: { enabled: false }
typo_checks: { enabled: false }
check_variables: { enabled: false }
check_calls: { enabled: true, too_many_arguments: true, missing_argument: true, argument_type_checks: lenient }
dead_assignments: { enabled: false }
check_usage_context: { enabled: true, foreach: { value_as_reference: true, traversable: true } }
reflection_checks: { enabled: false }
precedence_checks: { enabled: true, assignment_in_condition: true, comparison_of_bit_result: true }
basic_semantic_checks: { enabled: false }
unused_code: { enabled: false }
deprecation_checks: { enabled: false }
useless_function_calls: { enabled: false }
metrics_lack_of_cohesion_methods: { enabled: false }
metrics_coupling: { enabled: true, stable_code: { namespace_prefixes: { }, classes: { } } }
doctrine_parameter_binding: { enabled: false }
doctrine_entity_manager_injection: { enabled: false }
symfony_request_injection: { enabled: false }
doc_comment_fixes: { enabled: false }
php_code_sniffer:
config:
standard: WordPress
sniffs: { wordpress: { arrays: { array_declaration_sniff: true }, classes: { valid_class_name_sniff: true }, files: { file_name_sniff: true }, formatting: { multiple_statement_alignment_sniff: true }, functions: { function_call_signature_sniff: true, function_declaration_argument_spacing_sniff: true }, naming_conventions: { valid_function_name_sniff: true }, objects: { object_instantiation_sniff: true }, php: { discouraged_functions_sniff: true }, strings: { double_quote_usage_sniff: true }, white_space: { control_structure_spacing_sniff: true, operator_spacing_sniff: true, php_indent_sniff: true }, xss: { escape_output_sniff: true } } }
php_loc: true
php_pdepend: true
php_sim: true
php_changetracking: true

View file

@ -0,0 +1,61 @@
language: php
sudo: false
php:
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
env:
# - WP_VERSION=latest WP_MULTISITE=0
- WP_VERSION=5.0 WP_MULTISITE=0
- WP_VERSION=4.9 WP_MULTISITE=0
- WP_VERSION=4.8 WP_MULTISITE=0
- WP_VERSION=4.7 WP_MULTISITE=0
- WP_VERSION=4.6 WP_MULTISITE=0
- WP_VERSION=4.5 WP_MULTISITE=0
matrix:
include:
- php: 5.3
dist: precise
env: WP_VERSION=5.0 WP_MULTISITE=0
- php: 5.3
dist: precise
env: WP_VERSION=4.9 WP_MULTISITE=0
- php: 5.3
dist: precise
env: WP_VERSION=4.8 WP_MULTISITE=0
- php: 5.3
dist: precise
env: WP_VERSION=4.7 WP_MULTISITE=0
- php: 5.3
dist: precise
env: WP_VERSION=4.6 WP_MULTISITE=0
- php: 5.3
dist: precise
env: WP_VERSION=4.5 WP_MULTISITE=0
- php: 5.3
dist: precise
env: WP_VERSION=5.0 WP_MULTISITE=1
- php: 5.3
dist: precise
env: WP_VERSION=4.9 WP_MULTISITE=1
before_install:
- composer self-update
before_script:
- mysql -e "create database IF NOT EXISTS carbon_fields_tests;" -uroot
- bash tests/bin/install.sh carbon_fields_tests root '' localhost $WP_VERSION
script: ./vendor/bin/phpunit --coverage-clover=./tmp/clover.xml
after_script:
- wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover ./tmp/clover.xml

View file

@ -0,0 +1,22 @@
# Release Guide
## `htmlburger/carbon-fields`
1. Bump version numbers in `config.php` and `package.json` according to SemVer
1. Commit to `development` with commit message "Bump vX.X.X"
1. Merge all changes for the new version into `master`
1. Checkout `master`
1. Run `npm install && npm run build`
1. `git push origin master`
1. Create a new release in [Github](https://github.com/htmlburger/carbon-fields/releases/new) from the `master` branch
1. Enter the new version you set in `config.php` for `Tag version` and `Title`
1. Add a changelog for `Description`
1. Click `Publish release`
## `htmlburger/carbon-fields-plugin`
1. Update the version in `carbon-fields-plugin.php`, `readme.txt` and `composer.json` for `htmlburger/carbon-fields` to match the newly released version
1. Commit to `master`
1. Create a new release in [Github](https://github.com/htmlburger/carbon-fields-plugin/releases/new) from the `master` branch
1. Enter the new version for `Tag version` and `Title` (you can skip the changelog)
1. Click `Publish release`

View file

@ -0,0 +1,81 @@
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64"
config.vm.box_check_update = false
config.vm.network "forwarded_port", guest: 80, host: 8080
# Fix the DNS resolution speed. This actually slows down the unit tests speed
# (I assume due to base WP test suite)
# See http://serverfault.com/a/496612/80479
config.vm.provider "virtualbox" do |v|
v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
v.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
end
config.vm.synced_folder ".", "/home/vagrant/carbon-fields"
config.vm.synced_folder "../../../", "/var/www/"
# Install some software on the machine and setup unit tests environment
config.vm.provision "shell", inline: <<-SHELL
DBHOST=localhost
DBNAME=wp
DBUSER=wp
DBPASSWD=secret
echo -e "\n--- Update apt ---\n"
sudo apt-get -qq update
echo -e "\n--- Install some base packages ---\n"
sudo apt-get -y install vim curl build-essential python-software-properties nginx git subversion zip > /dev/null 2>&1
echo -e "\n--- Install PHP7 ---\n"
sudo LC_ALL=en_US.UTF-8 add-apt-repository ppa:ondrej/php
sudo apt-get -qq update
sudo apt-get install php7.0 php7.0-fpm php7.0-mysql -y
echo -e "\n--- Install composer ---\n"
sudo curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
echo -e "\n--- Install phpUnit ---\n"
su - vagrant -c 'sudo composer global require "phpunit/phpunit=5.0.*"'
echo 'PATH=$PATH:~/.composer/vendor/bin/' >> ~vagrant/.bash_profile && chown vagrant:vagrant ~vagrant/.bash_profile
echo -e "\n--- Install MySQL ---\n"
echo "mysql-server mysql-server/root_password password $DBPASSWD" | debconf-set-selections
echo "mysql-server mysql-server/root_password_again password $DBPASSWD" | debconf-set-selections
sudo apt-get -y install mysql-server-5.5
echo 'server {
listen 80;
server_name localhost;
root /var/www/;
index index.php index.html;
# Important for VirtualBox
sendfile off;
location / {
try_files $uri $uri/ =404;
}
location ~* \.php {
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_cache off;
fastcgi_index index.php;
}
}' > /etc/nginx/sites-available/default
service nginx restart;
echo -e "\n--- Setup MySQL ---\n"
mysql -uroot -p$DBPASSWD -e "CREATE DATABASE $DBNAME"
mysql -uroot -p$DBPASSWD -e "grant all privileges on $DBNAME.* to '$DBUSER'@'localhost' identified by '$DBPASSWD'"
su - vagrant -c "cd /home/vagrant/carbon-fields && ./tests/bin/install.sh $DBNAME $DBUSER $DBPASSWD"
SHELL
end

View file

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<ruleset name="Carbon Fields">
<description>Coding standards for Carbon Fields</description>
<exclude-pattern>tests/*</exclude-pattern>
<exclude-pattern>vendor/*</exclude-pattern>
<rule ref="WordPress-Core"/>
</ruleset>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="./tests/bootstrap.php"
colors="true"
stopOnError="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTestsThatDoNotTestAnything="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
backupGlobals="false"
>
<testsuites>
<testsuite name="Carbon Fields Test Suite">
<directory suffix=".php">./tests/unit-tests/</directory>
</testsuite>
</testsuites>
</phpunit>

View file

@ -0,0 +1,21 @@
# Carbon Fields Unit Tests
## Initial Setup
Install WordPress and the WP Unit Test lib using the `install.sh` script. Change to the plugin root directory and type:
$ tests/bin/install.sh <db-name> <db-user> <db-password> [db-host] [wp-version]
Sample usage:
$ tests/bin/install.sh carbon_fields_tests root root localhost 4.7
**Important**: Make sure that the `<db-name>` database has been created. Note that all data will be removed during testing.
## Running Tests
Simply change to the plugin root directory and type:
$ ./vendor/bin/phpunit
Refer to the [phpunit command line test runner reference](https://phpunit.de/manual/current/en/phpunit-book.html#textui) for more information and command line options.

View file

@ -0,0 +1,107 @@
#!/usr/bin/env bash
# See https://github.com/wp-cli/wp-cli/blob/master/templates/install-wp-tests.sh
# MySQL settings
if [ $# -lt 3 ]; then
echo "usage: $0 <db-name> <db-user> <db-pass> [db-host] [wp-version]"
exit 1
fi
# General variables
DB_NAME=$1
DB_USER=$2
DB_PASS=$3
DB_HOST=${4-localhost}
WP_VERSION=${5-latest}
BASEDIR="${PWD}"
# Handle Windows drive paths
if [ "$(expr substr $(uname -s) 1 5)" == "MINGW" ]; then
BASEDIR=$(echo $BASEDIR | sed -r 's/\/([a-zA-Z])\//\1:\//g')
fi
# Setup directory vars
WP_TESTS_DIR="${BASEDIR}/tmp/wordpress-tests-lib"
WP_CORE_DIR="${BASEDIR}/tmp/wordpress/"
set -ex
# Used to download a file to a certain location
download() {
if [ `which curl` ]; then
curl -s "$1" > "$2";
elif [ `which wget` ]; then
wget -nv -O "$2" "$1"
fi
}
# Determine WP version to download
wp_version() {
# Determine which version to download
if [ $WP_VERSION == 'latest' ]; then
local url='trunk'
else
local url="branches/$WP_VERSION"
fi
echo "$url"
}
# Install dependencies & autoloader (using Composer)
install_autoloader() {
composer install
}
# Install a certain version (or the latest one) of WordPress
install_wp() {
mkdir -p $WP_CORE_DIR
# Determine which version to download
local url=$(wp_version)
# Checkout the WordPress core
cd $WP_CORE_DIR
svn co --quiet http://develop.svn.wordpress.org/${url}/src/ .
# Copy the database settings (wp-content/db.php)
cp $BASEDIR/tests/misc/db.php $WP_CORE_DIR/wp-content/db.php
}
# Install the WordPress test suite
install_test_suite() {
# Portable in-place argument for both GNU sed and Mac OSX sed
if [[ $(uname -s) == 'Darwin' ]]; then
local ioption='-i .bak'
else
local ioption='-i'
fi
# Determine which version to download
local testsurl=$(wp_version)
# Prepare target directory and checkout WP test suite
mkdir -p $WP_TESTS_DIR
cd $WP_TESTS_DIR
svn co --quiet http://develop.svn.wordpress.org/${testsurl}/tests/phpunit/includes/
# Add the missing data/themedir1 directory
svn co --quiet http://develop.svn.wordpress.org/${testsurl}/tests/phpunit/data/themedir1/ ./data/themedir1
# Download base configuration file
download http://develop.svn.wordpress.org/${testsurl}/wp-tests-config-sample.php wp-tests-config.php
# Make sure colons are escaped (they might exist in Windows environments)
WP_CORE_DIR=$(echo $WP_CORE_DIR | sed -r 's/:/\\:/g')
# Replace variables in the config file
sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" wp-tests-config.php 2> /dev/null
sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" wp-tests-config.php 2> /dev/null
sed $ioption "s/yourusernamehere/$DB_USER/" wp-tests-config.php 2> /dev/null
sed $ioption "s/yourpasswordhere/$DB_PASS/" wp-tests-config.php 2> /dev/null
sed $ioption "s|localhost|${DB_HOST}|" wp-tests-config.php 2> /dev/null
sed $ioption "s/Test Blog/Carbon Fields Unit Tests/" wp-tests-config.php 2> /dev/null
}
install_autoloader
install_wp
install_test_suite

View file

@ -0,0 +1,84 @@
<?php
class Carbon_Fields_Tests_Bootstrap {
/**
* The bootstrap instance.
*
* @var Carbon_Fields_Tests_Bootstrap
*/
protected static $instance = null;
/**
* Directory where wordpress-tests-lib is installed
*
* @var string
*/
public $wp_tests_dir;
/**
* Testing directory.
*
* @var string
*/
public $tests_dir;
/**
* Plugin directory.
*
* @var string
*/
public $plugin_dir;
/**
* Setup the unit testing environment
*/
private function __construct() {
ini_set( 'display_errors','on' );
error_reporting( E_ALL );
$this->tests_dir = __DIR__;
$this->plugin_dir = dirname( $this->tests_dir );
$this->wp_tests_dir = getenv( 'WP_TESTS_DIR' ) ? getenv( 'WP_TESTS_DIR' ) : $this->plugin_dir . '/tmp/wordpress-tests-lib';
// load test function so tests_add_filter() is available
require_once( $this->wp_tests_dir . '/includes/functions.php' );
// load plugin
tests_add_filter( 'muplugins_loaded', array( $this, 'load_plugin' ) );
// load the WP testing environment
require_once( $this->wp_tests_dir . '/includes/bootstrap.php' );
// make sure query vars are prepared
global $wp;
if ( ! is_array( $wp->query_vars ) ) {
$wp->query_vars = array();
}
\Carbon_Fields\Carbon_Fields::instance()->booted = true;
}
/**
* Load the plugin
*/
public function load_plugin() {
require_once( $this->plugin_dir . '/vendor/autoload.php' );
}
/**
* Get the single tests boostrap instance
*
* @return Carbon_Fields_Tests_Bootstrap
*/
public static function instance() {
if ( is_null( static::$instance ) ) {
static::$instance = new self();
}
return static::$instance;
}
}
Carbon_Fields_Tests_Bootstrap::instance();

View file

@ -0,0 +1,5 @@
<?php
if ( ! defined( 'WP_USE_EXT_MYSQL' ) ) {
define( 'WP_USE_EXT_MYSQL', false );
}

View file

@ -0,0 +1,278 @@
<?php
use Mockery as M;
use Carbon_Fields\Pimple\Container as PimpleContainer;
use Carbon_Fields\Container\Container;
use Carbon_Fields\Container\Repository as ContainerRepository;
use Carbon_Fields\Toolset\Key_Toolset;
use Carbon_Fields\Container\Condition\Factory as ConditionFactory;
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
/**
* @group container
* @coversDefaultClass Carbon_Fields\Container\Container
*/
class ContainerTest extends WP_UnitTestCase {
public $containerId;
public $containerTitle;
public $containerType;
public $containerTypeUpperCase;
public $containerTypeSpaced;
public $containerTypeInvalid;
public $containerTypeClass;
public $containerTypeDatastoreClass;
public $containerTypeBrokenClass;
public $containerConditionFulfillableCollection;
public $containerConditionTranslatorJson;
public function setUp(): void {
$ioc = new PimpleContainer();
$ioc['container_repository'] = function( $ioc ) {
return new ContainerRepository();
};
$ioc['key_toolset'] = function( $ioc ) {
return new Key_Toolset();
};
$ioc['container_condition_factory'] = function( $ioc ) {
return new ConditionFactory( $ioc['container_conditions'] );
};
$ioc['container_condition_translator_array'] = function( $ioc ) {
return new \Carbon_Fields\Container\Fulfillable\Translator\Array_Translator( $ioc['container_condition_factory'] );
};
$ioc['container_condition_translator_json'] = function( $ioc ) {
return new \Carbon_Fields\Container\Fulfillable\Translator\Json_Translator( $ioc['container_condition_factory'] );
};
$ioc['container_condition_fulfillable_collection'] = $ioc->factory( function( $ioc ) {
return M::mock( 'Carbon_Fields\\Container\\Fulfillable\\Fulfillable_Collection' )->shouldIgnoreMissing();
} );
$ioc['container_conditions'] = function() {
return new PimpleContainer();
};
\Carbon_Fields\Carbon_Fields::instance()->install( $ioc );
$this->containerId = 'PageSettings';
$this->containerTitle = 'Page Settings';
$this->containerType = 'post_meta';
$this->containerTypeUpperCase = 'Post_Meta';
$this->containerTypeSpaced = 'Post Meta';
$this->containerTypeInvalid = '__no_such_container_type__';
$this->containerTypeClass = 'Carbon_Fields\Container\Post_Meta_Container';
$this->containerTypeDatastoreClass = 'Carbon_Fields\Datastore\Post_Meta_Datastore';
$this->containerTypeBrokenClass = 'Carbon_Fields\Container\Broken_Container';
$this->containerConditionFulfillableCollection = $ioc['container_condition_fulfillable_collection'];
$this->containerConditionTranslatorJson = $ioc['container_condition_translator_json'];
}
public function tearDown(): void {
\Carbon_Fields\Carbon_Fields::instance()->install( new PimpleContainer() );
}
/**
* @covers ::make
* @covers ::factory
*/
public function testMakePostMetaContainer() {
$container = Container::factory( $this->containerType, $this->containerTitle );
$this->assertEquals( $this->containerTitle, $container->title );
}
/**
* @covers ::make
* @covers ::factory
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage Unknown container "".
*/
public function testExceptionIsThrownWhenContainerTypeIsEmpty() {
$container = Container::factory( '', $this->containerTitle );
}
/**
* @covers ::make
* @covers ::factory
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage Unknown container "__no_such_container_type__".
*/
public function testExceptionIsThrownWhenContainerTypeIsInvalid() {
$container = Container::factory( $this->containerTypeInvalid, $this->containerTitle );
}
/**
* @covers ::make
* @covers ::factory
*/
public function testBrokenContainerIsReturnedWhenDebugIsDisabledAndContainerIsInvalid() {
$old_val = Incorrect_Syntax_Exception::$throw_errors;
Incorrect_Syntax_Exception::$throw_errors = false;
$container = Container::factory( $this->containerTypeInvalid, $this->containerTitle );
$this->assertInstanceOf( $this->containerTypeBrokenClass, $container );
Incorrect_Syntax_Exception::$throw_errors = $old_val;
}
/**
* @covers ::make
* @covers ::factory
*/
public function testContainerTypeCaseIsIgnored() {
$container = Container::factory( $this->containerTypeUpperCase, $this->containerTitle );
$this->assertInstanceOf( $this->containerTypeClass, $container );
}
/**
* @covers ::make
* @covers ::factory
*/
public function testSpacesInContainerTypeAreSupported() {
$container = Container::factory( $this->containerTypeSpaced, $this->containerTitle );
$this->assertTrue(true); // no exception should be thrown
}
/**
* @covers ::make
* @covers ::factory
*/
public function testSameContainerNamesDoNotGenerateIdenticalIds() {
$container1 = Container::factory( $this->containerType, $this->containerTitle );
$container2 = Container::factory( $this->containerType, $this->containerTitle );
$this->assertNotEquals( $container1->get_id(), $container2->get_id() );
}
/**
* @covers ::make
* @covers ::factory
*/
public function testSameContainerNameAddsNumericalSuffix() {
$container1 = Container::factory( $this->containerType, $this->containerTitle );
$container2 = Container::factory( $this->containerType, $this->containerTitle );
$this->assertEquals( $container1->get_id() . '1', $container2->get_id() );
}
/**
* @covers ::__construct
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage Empty container title is not supported
*/
public function testExceptionIsThrownWhenContainerTitleIsEmpty() {
$container = new $this->containerTypeClass( $this->containerId, '', $this->containerType, $this->containerConditionFulfillableCollection, $this->containerConditionTranslatorJson );
}
/**
* @covers ::__construct
*/
public function testNonAsciiContainerTitlesAreHandledProperly() {
// This text includes a capital cyrillic letter ... it actually assures that
// container titles in non-english are converted to lowercase
$container = new $this->containerTypeClass( $this->containerId, 'bulgarian: България', $this->containerType, $this->containerConditionFulfillableCollection, $this->containerConditionTranslatorJson );
$this->assertEquals( 'bulgarian: България', $container->title );
}
/**
* @covers ::set_datastore
* @covers ::get_datastore
* @covers ::has_default_datastore
*/
public function testSetDatastore_Default_ReturnDefault() {
$datastore = M::mock( $this->containerTypeDatastoreClass )->shouldIgnoreMissing();
$container = new $this->containerTypeClass( $this->containerId, $this->containerTitle, $this->containerType, $this->containerConditionFulfillableCollection, $this->containerConditionTranslatorJson );
$this->assertEquals( true, $container->has_default_datastore() );
$this->assertInstanceOf( $this->containerTypeDatastoreClass, $container->get_datastore() );
$container->set_datastore( $datastore, true );
$this->assertEquals( true, $container->has_default_datastore() );
$this->assertEquals( $datastore, $container->get_datastore() );
}
/**
* @covers ::set_datastore
* @covers ::get_datastore
* @covers ::has_default_datastore
*/
public function testSetDatastore_DefaultDefault2_ReturnDefault2() {
$datastore1 = M::mock( $this->containerTypeDatastoreClass )->shouldIgnoreMissing();
$datastore2 = M::mock( $this->containerTypeDatastoreClass )->shouldIgnoreMissing();
$container = new $this->containerTypeClass( $this->containerId, $this->containerTitle, $this->containerType, $this->containerConditionFulfillableCollection, $this->containerConditionTranslatorJson );
$container->set_datastore( $datastore1, true );
$container->set_datastore( $datastore2, true );
$this->assertEquals( $datastore2, $container->get_datastore() );
}
/**
* @covers ::set_datastore
* @covers ::get_datastore
* @covers ::has_default_datastore
*/
public function testSetDatastore_Override_ReturnOverride() {
$datastore = M::mock( $this->containerTypeDatastoreClass )->shouldIgnoreMissing();
$container = new $this->containerTypeClass( $this->containerId, $this->containerTitle, $this->containerType, $this->containerConditionFulfillableCollection, $this->containerConditionTranslatorJson );
$container->set_datastore( $datastore, false );
$this->assertEquals( false, $container->has_default_datastore() );
$this->assertEquals( $datastore, $container->get_datastore() );
}
/**
* @covers ::set_datastore
* @covers ::get_datastore
* @covers ::has_default_datastore
*/
public function testSetDatastore_OverrideOverride2_ReturnOverride2() {
$datastore1 = M::mock( $this->containerTypeDatastoreClass )->shouldIgnoreMissing();
$datastore2 = M::mock( $this->containerTypeDatastoreClass )->shouldIgnoreMissing();
$container = new $this->containerTypeClass( $this->containerId, $this->containerTitle, $this->containerType, $this->containerConditionFulfillableCollection, $this->containerConditionTranslatorJson );
$container->set_datastore( $datastore1, false );
$container->set_datastore( $datastore2, false );
$this->assertEquals( false, $container->has_default_datastore() );
$this->assertEquals( $datastore2, $container->get_datastore() );
}
/**
* @covers ::set_datastore
* @covers ::get_datastore
* @covers ::has_default_datastore
*/
public function testSetDatastore_DefaultOverride_ReturnOverride() {
$default_datastore = M::mock( $this->containerTypeDatastoreClass )->shouldIgnoreMissing();
$override_datastore = M::mock( $this->containerTypeDatastoreClass )->shouldIgnoreMissing();
$container = new $this->containerTypeClass( $this->containerId, $this->containerTitle, $this->containerType, $this->containerConditionFulfillableCollection, $this->containerConditionTranslatorJson );
$container->set_datastore( $default_datastore, true );
$this->assertEquals( true, $container->has_default_datastore() );
$this->assertEquals( $default_datastore, $container->get_datastore() );
$container->set_datastore( $override_datastore, false );
$this->assertEquals( false, $container->has_default_datastore() );
$this->assertEquals( $override_datastore, $container->get_datastore() );
}
/**
* @covers ::set_datastore
* @covers ::get_datastore
* @covers ::has_default_datastore
*/
public function testSetDatastore_DefaultOverrideDefault2_ReturnOverride() {
$default_datastore = M::mock( $this->containerTypeDatastoreClass )->shouldIgnoreMissing();
$override_datastore = M::mock( $this->containerTypeDatastoreClass )->shouldIgnoreMissing();
$container = new $this->containerTypeClass( $this->containerId, $this->containerTitle, $this->containerType, $this->containerConditionFulfillableCollection, $this->containerConditionTranslatorJson );
$container->set_datastore( $default_datastore, true );
$container->set_datastore( $override_datastore, false );
$container->set_datastore( $default_datastore, true );
$this->assertEquals( false, $container->has_default_datastore() );
$this->assertEquals( $override_datastore, $container->get_datastore() );
}
}

View file

@ -0,0 +1,343 @@
<?php
use Mockery as M;
use Carbon_Fields\Pimple\Container as PimpleContainer;
use Carbon_Fields\Container\Fulfillable\Fulfillable_Collection;
use Carbon_Fields\Container\Condition\Factory as ConditionFactory;
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
/**
* @coversDefaultClass Carbon_Fields\Container\Fulfillable\Fulfillable_Collection
*/
class FulfillableCollectionTest extends WP_UnitTestCase {
public $subject;
public $condition_factory;
public function setUp(): void {
$ioc = new PimpleContainer();
$ioc->register( new \Carbon_Fields\Provider\Container_Condition_Provider() );
\Carbon_Fields\Carbon_Fields::instance()->install( $ioc );
$this->subject = $ioc['container_condition_fulfillable_collection'];
$this->condition_factory = $ioc['container_condition_factory'];
}
public function tearDown(): void {
M::close();
$this->condition_factory = null;
$this->subject = null;
}
/**
* @covers ::where
* @covers ::or_where
* @covers ::is_fulfilled
*/
public function testWhereWithBasicArgumentsIsFulfilled() {
$this->subject->where( 'post_type', '=', 'post' );
$environment = array( 'post_type' => 'post' );
$this->assertTrue( $this->subject->is_fulfilled( $environment ) );
}
/**
* @covers ::where
* @covers ::is_fulfilled
*/
public function testWhereWithBasicArgumentsIsNotFulfilled() {
$this->subject->where( 'post_type', '=', 'post' );
$environment = array( 'post_type' => 'page' );
$this->assertFalse( $this->subject->is_fulfilled( $environment ) );
}
/**
* @covers ::where
* @covers ::is_fulfilled
*/
public function testWhereWithSkippedComparerIsFulfilled() {
$this->subject->where( 'post_type', 'post' );
$environment = array( 'post_type' => 'post' );
$this->assertTrue( $this->subject->is_fulfilled( $environment ) );
}
/**
* @covers ::where
* @covers ::is_fulfilled
*/
public function testWhereWithSkippedComparerIsNotFulfilled() {
$this->subject->where( 'post_type', 'post' );
$environment = array( 'post_type' => 'page' );
$this->assertFalse( $this->subject->is_fulfilled( $environment ) );
}
/**
* @covers ::where
* @covers ::is_fulfilled
*/
public function testWhereWithArrayArgumentsIsFulfilled() {
$this->subject->where( array(
array(
'type' => 'post_type',
'value' => 'post',
),
) );
$environment = array( 'post_type' => 'post' );
$this->assertTrue( $this->subject->is_fulfilled( $environment ) );
}
/**
* @covers ::where
* @covers ::is_fulfilled
*/
public function testWhereWithArrayArgumentsIsNotFulfilled() {
$this->subject->where( array(
array(
'type' => 'post_type',
'value' => 'post',
),
) );
$environment = array( 'post_type' => 'page' );
$this->assertFalse( $this->subject->is_fulfilled( $environment ) );
}
/**
* @covers ::where
* @covers ::is_fulfilled
*/
public function testWhereWithCallableIsFulfilled() {
$this->subject->where( function( $c ) {
$c->where( 'post_type', 'post' );
} );
$environment = array( 'post_type' => 'post' );
$this->assertTrue( $this->subject->is_fulfilled( $environment ) );
}
/**
* @covers ::where
* @covers ::is_fulfilled
*/
public function testWhereWithCallableIsNotFulfilled() {
$this->subject->where( function( $c ) {
$c->where( 'post_type', 'post' );
} );
$environment = array( 'post_type' => 'page' );
$this->assertFalse( $this->subject->is_fulfilled( $environment ) );
}
/**
* @covers ::where
* @covers ::is_fulfilled
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
*/
public function testWhereWithUnsupportedConditionTypeThrowsException() {
$this->subject->where( 'unsupported_condition_type', 'post' );
}
/**
* @covers ::add_fulfillable
* @covers ::get_fulfillables
*/
public function testAddFulfillableAddsFulfillable() {
$fulfillable = M::mock( 'Carbon_Fields\\Container\\Fulfillable\\Fulfillable' );
$fulfillable_comparison = 'AND';
$this->assertSame( 0, count( $this->subject->get_fulfillables() ) );
$this->subject->add_fulfillable( $fulfillable, $fulfillable_comparison );
$this->assertSame( 1, count( $this->subject->get_fulfillables() ) );
$fulfillables = $this->subject->get_fulfillables();
$this->assertSame( $fulfillable, $fulfillables[0]['fulfillable'] );
$this->assertSame( $fulfillable_comparison, $fulfillables[0]['fulfillable_comparison'] );
}
/**
* @covers ::add_fulfillable
* @covers ::get_fulfillables
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
*/
public function testAddFulfillableThrowsExceptionOnInvalidComparison() {
$fulfillable = M::mock( 'Carbon_Fields\\Container\\Fulfillable\\Fulfillable' );
$fulfillable_comparison = 'UNSUPPORTED_COMPARISON_TYPE';
$this->subject->add_fulfillable( $fulfillable, $fulfillable_comparison );
}
/**
* @covers ::filter
*/
public function testFilterRemovesUnlistedConditionTypes() {
$this->subject->where( 'post_id', 1 );
$this->subject->where( 'post_type', 'post' );
$filtered = $this->subject->filter( array( 'post_type' ) );
$this->assertTrue( count( $filtered->get_fulfillables() ) === 1, 'Filtered collection should contain 1 fulfillable only' );
$this->assertTrue( count( $this->subject->get_fulfillables() ) === 2, 'Subject collection should remain unmodified' );
}
/**
* @covers ::filter
*/
public function testFilterRemovesUnlistedConditionTypesRecursively() {
$this->subject->where( 'post_type', 'post' );
$this->subject->where( function( $c ) {
$c->where( 'post_id', 1 );
$c->where( function( $c ) {
$c->where( 'post_id', 1 );
} );
} );
$filtered = $this->subject->filter( array( 'post_type' ) );
$this->assertTrue( count( $filtered->get_fulfillables() ) === 1, 'Filtered collection should contain 1 fulfillable only' );
$this->assertTrue( count( $this->subject->get_fulfillables() ) === 2, 'Subject collection should remain unmodified' );
}
/**
* @covers ::evaluate
*/
public function testEvaluateReplacesFulfilledConditionsWithBooleanTrue() {
$this->subject->where( 'post_id', 1 );
$this->subject->where( 'post_template', 'default' );
$evaluated = $this->subject->evaluate( array( 'post_id' ), array( 'post_id' => 1 ) );
$ef = $evaluated->get_fulfillables();
$expected = array(
array(
'type' => 'boolean',
'value' => true,
),
array(
'type' => 'post_template',
'value' => 'default',
),
);
$received = array();
foreach ( $ef as $tuple ) {
$received[] = array(
'type' => $this->condition_factory->get_type( get_class( $tuple['fulfillable'] ) ),
'value' => $tuple['fulfillable']->get_value(),
);
}
$this->assertSame( $expected, $received );
}
/**
* @covers ::evaluate
*/
public function testEvaluateReplacesFailingConditionsWithBooleanFalse() {
$this->subject->where( 'post_id', 1 );
$this->subject->where( 'post_template', 'default' );
$evaluated = $this->subject->evaluate( array( 'post_id' ), array( 'post_id' => 2 ) );
$ef = $evaluated->get_fulfillables();
$expected = array(
array(
'type' => 'boolean',
'value' => false,
),
array(
'type' => 'post_template',
'value' => 'default',
),
);
$received = array();
foreach ( $ef as $tuple ) {
$received[] = array(
'type' => $this->condition_factory->get_type( get_class( $tuple['fulfillable'] ) ),
'value' => $tuple['fulfillable']->get_value(),
);
}
$this->assertSame( $expected, $received );
}
/**
* @covers ::evaluate
*/
public function testEvaluateReplacesComparisonOperatorForBoolean() {
$this->subject->where( 'post_id', '>', 1 );
$this->subject->where( 'post_template', 'default' );
$evaluated = $this->subject->evaluate( array( 'post_id' ), array( 'post_id' => 1 ) );
$ef = $evaluated->get_fulfillables();
$expected = array(
array(
'type' => 'boolean',
'comparison_operator' => '=',
'value' => false,
),
array(
'type' => 'post_template',
'comparison_operator' => '=',
'value' => 'default',
),
);
$received = array();
foreach ( $ef as $tuple ) {
$received[] = array(
'type' => $this->condition_factory->get_type( get_class( $tuple['fulfillable'] ) ),
'comparison_operator' => $tuple['fulfillable']->get_comparison_operator(),
'value' => $tuple['fulfillable']->get_value(),
);
}
$this->assertSame( $expected, $received );
}
/**
* @covers ::is_fulfilled
*/
public function testIsFulfilledWhenEmpty() {
$environment = array( );
$this->assertTrue( $this->subject->is_fulfilled( $environment ) );
}
/**
* @covers ::is_fulfilled
*/
public function testIsFulfilledWithSingleConditionWhenAllConditionsAreFulfilled() {
$this->subject->where( 'post_type', 'post' );
$environment = array( 'post_type' => 'post' );
$this->assertTrue( $this->subject->is_fulfilled( $environment ) );
}
/**
* @covers ::is_fulfilled
*/
public function testIsFulfilledWithMultipleConditionsWhenAllConditionsAreFulfilled() {
$this->subject->where( 'post_type', 'post' );
$this->subject->where( 'post_id', 1 );
$environment = array( 'post_type' => 'post', 'post_id' => 1 );
$this->assertTrue( $this->subject->is_fulfilled( $environment ) );
}
/**
* @covers ::is_fulfilled
*/
public function testIsFulfilledWithNestedConditionsWhenAllConditionsAreFulfilled() {
$this->subject->where( 'post_type', 'post' );
$this->subject->where( function( $c ) {
$c->where( 'post_id', 1 );
} );
$environment = array( 'post_type' => 'post', 'post_id' => 1 );
$this->assertTrue( $this->subject->is_fulfilled( $environment ) );
}
/**
* @covers ::is_fulfilled
*/
public function testIsFulfilledWhenOneConditionIsFulfilled() {
$this->subject->where( 'post_id', 1 );
$this->subject->or_where( 'post_type', 'post' );
$environment = array( 'post_id' => 1, 'post_type' => 'page' );
$this->assertTrue( $this->subject->is_fulfilled( $environment ) );
}
/**
* @covers ::is_fulfilled
*/
public function testIsNotFulfilledWhenNoConditionsAreFulfilled() {
$this->subject->where( 'post_id', 1 );
$this->subject->or_where( 'post_type', 'post' );
$environment = array( 'post_id' => 0, 'post_type' => 'page' );
$this->assertFalse( $this->subject->is_fulfilled( $environment ) );
}
}

View file

@ -0,0 +1,265 @@
<?php
use Mockery as M;
use Carbon_Fields\Pimple\Container as PimpleContainer;
use Carbon_Fields\Container\Fulfillable\Fulfillable_Collection;
use Carbon_Fields\Container\Condition\Factory as ConditionFactory;
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
/**
* WARNING: the array translator produces logically identical results but not 100% identical representations when dealing with nested collections
*
* @coversDefaultClass Carbon_Fields\Container\Fulfillable\Translator\Array_Translator
*/
class ArrayTranslatorTest extends WP_UnitTestCase {
public $subject;
public function setUp(): void {
$ioc = new PimpleContainer();
/* Conditions */
$ioc['container_condition_factory'] = function( $ioc ) {
return new ConditionFactory( $ioc['container_conditions'] );
};
$ioc['container_condition_fulfillable_collection'] = $ioc->factory( function( $ioc ) {
return new Fulfillable_Collection( $ioc['container_condition_factory'], $ioc['container_condition_translator_array'] );
} );
$ioc['container_conditions'] = function() {
return new PimpleContainer();
};
$cc_ioc = $ioc['container_conditions'];
$cc_ioc['post_id'] = $cc_ioc->factory( function( $cc_ioc ) use ( $ioc ) {
$condition = new \Carbon_Fields\Container\Condition\Post_ID_Condition();
$condition->set_comparers( $ioc['container_condition_comparer_collections']['generic'] );
return $condition;
} );
$cc_ioc['post_type'] = $cc_ioc->factory( function( $cc_ioc ) use ( $ioc ) {
$condition = new \Carbon_Fields\Container\Condition\Post_Type_Condition();
$condition->set_comparers( $ioc['container_condition_comparer_collections']['nonscalar'] );
return $condition;
} );
/* Comparers */
$ioc['container_condition_comparers'] = function( $ioc ) {
return new PimpleContainer();
};
$ioc['container_condition_comparers']['equality'] = function() {
return new \Carbon_Fields\Container\Condition\Comparer\Equality_Comparer();
};
$ioc['container_condition_comparers']['contain'] = function() {
return new \Carbon_Fields\Container\Condition\Comparer\Contain_Comparer();
};
$ioc['container_condition_comparers']['scalar'] = function() {
return new \Carbon_Fields\Container\Condition\Comparer\Scalar_Comparer();
};
$ioc['container_condition_comparers']['custom'] = function() {
return new \Carbon_Fields\Container\Condition\Comparer\Custom_Comparer();
};
$ioc['container_condition_comparer_collections'] = function( $ioc ) {
return new PimpleContainer();
};
$ioc['container_condition_comparer_collections']['generic'] = function( $cccc_ioc ) use ( $ioc ) {
return array(
$ioc['container_condition_comparers']['equality'],
$ioc['container_condition_comparers']['contain'],
$ioc['container_condition_comparers']['scalar'],
$ioc['container_condition_comparers']['custom'],
);
};
$ioc['container_condition_comparer_collections']['nonscalar'] = function( $cccc_ioc ) use ( $ioc ) {
return array(
$ioc['container_condition_comparers']['equality'],
$ioc['container_condition_comparers']['contain'],
$ioc['container_condition_comparers']['custom'],
);
};
/* Translators */
$ioc['container_condition_translator_array'] = function( $ioc ) {
return new \Carbon_Fields\Container\Fulfillable\Translator\Array_Translator( $ioc['container_condition_factory'] );
};
\Carbon_Fields\Carbon_Fields::instance()->install( $ioc );
$this->subject = $ioc['container_condition_translator_array'];
}
public function tearDown(): void {
M::close();
$this->subject = null;
}
/**
* @covers ::fulfillable_to_foreign
*/
public function testFulfillableToForeignWithCondition() {
$factory = \Carbon_Fields\Carbon_Fields::resolve( 'container_condition_factory' );
$condition = $factory->make( 'post_type' );
$condition->set_comparison_operator( '!=' );
$condition->set_value( 'post' );
$expected = array(
'type' => 'post_type',
'compare' => '!=',
'value' => 'post',
);
$received = $this->subject->fulfillable_to_foreign( $condition );
$this->assertSame( $expected, $received );
}
/**
* @covers ::foreign_to_fulfillable
*/
public function testForeignToFulfillableWithCondition() {
$factory = \Carbon_Fields\Carbon_Fields::resolve( 'container_condition_factory' );
$condition = $factory->make( 'post_type' );
$condition->set_comparison_operator( '!=' );
$condition->set_value( 'post' );
$expected = $condition;
$received = $this->subject->foreign_to_fulfillable( array(
'type' => 'post_type',
'compare' => '!=',
'value' => 'post',
) );
$this->assertEquals( $expected, $received );
}
/**
* @covers ::fulfillable_to_foreign
*/
public function testFulfillableToForeignWithCollection() {
$fulfillable = \Carbon_Fields\Carbon_Fields::resolve( 'container_condition_fulfillable_collection' );
$fulfillable->where( 'post_type', '!=', 'post' );
$fulfillable->where( 'post_id', '!=', 1 );
$expected = array(
'relation' => 'AND',
array(
'type' => 'post_type',
'compare' => '!=',
'value' => 'post',
),
array(
'type' => 'post_id',
'compare' => '!=',
'value' => 1,
),
);
$received = $this->subject->fulfillable_to_foreign( $fulfillable );
$this->assertSame( $expected, $received );
}
/**
* @covers ::foreign_to_fulfillable
*/
public function testForeignToFulfillableWithCollection() {
$fulfillable = \Carbon_Fields\Carbon_Fields::resolve( 'container_condition_fulfillable_collection' );
$fulfillable->where( 'post_type', '!=', 'post' );
$fulfillable->where( 'post_id', '!=', 1 );
$expected = $fulfillable;
$received = $this->subject->foreign_to_fulfillable( array(
'relation' => 'AND',
array(
'type' => 'post_type',
'compare' => '!=',
'value' => 'post',
),
array(
'type' => 'post_id',
'compare' => '!=',
'value' => 1,
),
) );
$this->assertEquals( $expected, $received );
}
/**
* @covers ::fulfillable_to_foreign
*/
public function testFulfillableToForeignWithNestedCollection() {
$fulfillable = \Carbon_Fields\Carbon_Fields::resolve( 'container_condition_fulfillable_collection' );
$fulfillable->where( 'post_type', '!=', 'post' );
$fulfillable->where( function( $c ) {
$c->where( 'post_id', '!=', 1 );
$c->or_where( 'post_id', '!=', 2 );
} );
$expected = array(
'relation' => 'AND',
array(
'type' => 'post_type',
'compare' => '!=',
'value' => 'post',
),
array(
'relation' => 'OR',
array(
'relation' => 'AND',
array(
'type' => 'post_id',
'compare' => '!=',
'value' => 1,
),
),
array(
'relation' => 'OR',
array(
'type' => 'post_id',
'compare' => '!=',
'value' => 2,
),
),
),
);
$received = $this->subject->fulfillable_to_foreign( $fulfillable );
$this->assertSame( $expected, $received );
}
/**
* @covers ::foreign_to_fulfillable
*/
public function testForeignToFulfillableWithNestedCollection() {
$fulfillable = \Carbon_Fields\Carbon_Fields::resolve( 'container_condition_fulfillable_collection' );
$fulfillable->where( 'post_type', '!=', 'post' );
$fulfillable->where( function( $c ) {
$c->or_where( 'post_id', '!=', 1 );
$c->or_where( 'post_id', '!=', 2 );
} );
$expected = $fulfillable;
$received = $this->subject->foreign_to_fulfillable( array(
'relation' => 'AND',
array(
'type' => 'post_type',
'compare' => '!=',
'value' => 'post',
),
array(
'relation' => 'OR',
array(
'type' => 'post_id',
'compare' => '!=',
'value' => 1,
),
array(
'type' => 'post_id',
'compare' => '!=',
'value' => 2,
),
),
) );
$this->assertEquals( $expected, $received );
}
}

View file

@ -0,0 +1,149 @@
<?php
use Mockery as M;
use Carbon_Fields\Container\Repository;
use Carbon_Fields\Container\Container;
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
/**
* @coversDefaultClass Carbon_Fields\Container\Repository
*/
class RepositoryTest extends WP_UnitTestCase {
public $containerId;
public $containerTitle;
public $containerType;
public $containerClass;
public $containerDuplicateTitleId;
public $repository;
public function setUp(): void {
$this->containerId = 'carbon_fields_container_page_settings';
$this->containerTitle = 'Page Settings';
$this->containerType = 'post_meta';
$this->containerClass = 'Carbon_Fields\Container\Post_Meta_Container';
$this->containerDuplicateTitleId = 'carbon_fields_container_page_settings1';
$this->repository = new Repository();
}
public function tearDown(): void {
M::close();
$this->repository = null;
}
public function getContainerMock( $callable = null ) {
if ( is_callable( $callable ) ) {
$mock = M::mock( $this->containerClass, $callable );
} else {
$mock = M::mock( $this->containerClass );
}
$mock->shouldIgnoreMissing();
$mock->id = $this->containerId;
$mock->title = $this->containerTitle;
$mock->type = $this->containerType;
return $mock;
}
/**
* @covers ::register_container
* @covers ::initialize_containers
*/
public function testInitializeContainersCallsInitOnce() {
$container = $this->getContainerMock( function( $mock ) {
$mock->shouldReceive( 'init' )->once();
} );
$this->repository->register_container( $container );
$this->repository->initialize_containers();
$this->assertTrue( true ); // rely on Mockery expectations to fail the test
}
/**
* @covers ::register_container
* @covers ::initialize_containers
*/
public function testInitializeContainersReturnsContainers() {
$container = $this->getContainerMock();
$expected = array( $container );
$this->repository->register_container( $container );
$received = $this->repository->initialize_containers();
$this->assertEquals( $expected, $received );
}
/**
* @covers ::register_container
* @covers ::initialize_containers
*/
public function testInitializeContainersReturnsOnlyNewContainers() {
$container1 = $this->getContainerMock();
$container2 = $this->getContainerMock();
$expected1 = array( $container1 );
$expected2 = array( $container2 );
$this->repository->register_container( $container1 );
$received1 = $this->repository->initialize_containers();
$this->assertEquals( $expected1, $received1 );
$this->repository->register_container( $container2 );
$received2 = $this->repository->initialize_containers();
$this->assertEquals( $expected2, $received2 );
}
/**
* @covers ::get_active_containers
*/
public function testGetActiveContainers() {
$container1 = $this->getContainerMock( function( $mock ) {
$mock->shouldReceive( 'is_active' )->andReturn( true );
} );
$container2 = $this->getContainerMock( function( $mock ) {
$mock->shouldReceive( 'is_active' )->andReturn( false );
} );
$expected = array( $container1 );
$this->repository->register_container( $container1 );
$this->repository->register_container( $container2 );
$received = $this->repository->get_active_containers();
$this->assertEquals( $expected, $received );
}
/**
* @covers ::get_unique_container_id
*/
public function testGetUniqueContainerId_InvalidCharacters_Stripped() {
$expected = $this->containerId;
$received = $this->repository->get_unique_container_id( $this->containerTitle );
$this->assertEquals( $expected, $received );
}
/**
* @covers ::get_unique_container_id
* @covers ::register_container
*/
public function testGetUniqueContainerId_IdenticalTitles_ReturnsDifferentIds() {
$container = $this->getContainerMock();
$this->repository->register_container( $container );
$received = $this->repository->get_unique_container_id( $container->title );
$this->assertNotEquals( $container->get_id(), $received );
}
/**
* @covers ::get_unique_container_id
* @covers ::register_container
*/
public function testGetUniqueContainerId_IdenticalTitles_AddsNumericalSuffix() {
$container = $this->getContainerMock();
$container->shouldReceive( 'get_id' )->andReturn( $this->containerId );
$this->repository->register_container( $container );
$received = $this->repository->get_unique_container_id( $container->title );
$this->assertEquals( $this->containerDuplicateTitleId, $received );
}
}

View file

@ -0,0 +1,50 @@
<?php
use Mockery as M;
use Carbon_Fields\Field\Color_Field;
use Carbon_Fields\Value_Set\Value_Set;
/**
* @group field
* @coversDefaultClass Carbon_Fields\Field\Color_Field
*/
class ColorFieldTest extends WP_UnitTestCase {
public $subject;
public function setUp(): void {
$this->subject = M::mock( 'Carbon_Fields\Field\Color_Field' )->makePartial();
}
public function tearDown(): void {
M::close();
unset( $this->subject );
}
/**
* @covers ::get_palette
* @covers ::set_palette
*/
public function testSetPaletteUpdatesPalette() {
$expected1 = array( '#FF0000' );
$expected2 = array( '#00FF00' );
$this->subject->set_palette( $expected1 );
$this->assertSame( $expected1, $this->subject->get_palette() );
$this->subject->set_palette( $expected2 );
$this->assertSame( $expected2, $this->subject->get_palette() );
}
/**
* @covers ::get_alpha_enabled
* @covers ::set_alpha_enabled
*/
public function testSetAlphaEnabledUpdatesAlphaEnabled() {
$expected1 = false;
$expected2 = true;
$this->assertSame( $expected1, $this->subject->get_alpha_enabled() );
$this->subject->set_alpha_enabled( $expected2 );
$this->assertSame( $expected2, $this->subject->get_alpha_enabled() );
}
}

View file

@ -0,0 +1,189 @@
<?php
use Carbon_Fields\Field\Field;
/**
* @coversDefaultClass Carbon_Fields\Field\Field
*/
class FieldConditionalLogicTest extends WP_UnitTestCase {
private $field;
public function setUp(): void {
$this->field = Field::make( 'text', 'color' );
}
public function tearDown(): void {
unset( $this->field );
}
/**
* @covers ::set_conditional_logic
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage should be an array
*/
public function testErrorIsThrownWhenCondLogicIsNotArray() {
$this->field->set_conditional_logic( 'this should actually be array' );
}
/**
* @covers ::set_conditional_logic
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
*/
public function testErrorIsThrownWhenFlatArrayIsProvided() {
$this->field->set_conditional_logic( array(
'field' => 'is_product',
'value' => 'yes',
) );
}
/**
* Private helper method for brevity
*/
public function verify_cond_logic( $user_defined_cond_logic, $expected_parsed_cond_logic ) {
$actual_parsed_cond_logic = $this->field
->set_conditional_logic( $user_defined_cond_logic )
->get_conditional_logic();
$this->assertEquals(
$expected_parsed_cond_logic,
$actual_parsed_cond_logic
);
}
/**
* @covers ::set_conditional_logic
* @covers ::get_conditional_logic
*/
public function testBasicCondLogic() {
$user_defined_cond_logic = array(
array(
'field' => 'is_product',
'value' => 'yes',
)
);
$expected_parsed_cond_logic = array(
'relation' => 'AND',
'rules' => array(
array(
'field' => 'is_product',
'value' => 'yes',
'compare' => '=',
)
)
);
$this->verify_cond_logic(
$user_defined_cond_logic,
$expected_parsed_cond_logic
);
}
/**
* @covers ::set_conditional_logic
* @covers ::get_conditional_logic
*/
public function testValueDefaultsToEmptyString() {
$user_defined_cond_logic = array(
array(
'field' => 'is_product',
'compare' => '!=',
)
);
$expected_parsed_cond_logic = array(
'relation' => 'AND',
'rules' => array(
array(
'field' => 'is_product',
'value' => '',
'compare' => '!=',
)
)
);
$this->verify_cond_logic(
$user_defined_cond_logic,
$expected_parsed_cond_logic
);
}
/**
* @covers ::set_conditional_logic
* @covers ::get_conditional_logic
*/
public function testRelationOperatorIsProvidedInLowercase() {
$user_defined_cond_logic = array(
'relation' => 'or',
array(
'field' => 'is_product',
'value' => 'yes',
)
);
$expected_parsed_cond_logic = array(
'relation' => 'OR',
'rules' => array(
array(
'field' => 'is_product',
'value' => 'yes',
'compare' => '=',
)
)
);
$this->verify_cond_logic(
$user_defined_cond_logic,
$expected_parsed_cond_logic
);
}
/**
* @covers ::set_conditional_logic
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage Invalid relation
*/
public function testBadRelationOperatorThrowsError() {
$this->field->set_conditional_logic( array(
'relation' => 'maybe',
array(
'field' => 'is_product',
'value' => 'yes',
)
) );
}
/**
* @covers ::set_conditional_logic
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage compare operator
*/
public function testBadCompareOperatorThrowsError() {
$this->field->set_conditional_logic( array(
array(
'field' => 'is_product',
'value' => 'yes',
'compare' => '!==' // There is no `!==` operator
)
) );
}
/**
* @covers ::set_conditional_logic
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage An array is expected
*/
public function testInCompareOperatorRequiresArrayAsValue() {
$this->field->set_conditional_logic( array(
array(
'field' => 'is_product',
'value' => 'yes',
'compare' => 'IN'
)
) );
}
}

View file

@ -0,0 +1,26 @@
<?php
/**
* @group field
* @coversDefaultClass Carbon_Fields\Field\Field
*/
class FieldGetSetId extends WP_UnitTestCase {
public $field;
public function setUp(): void {
$this->field = $this->getMockForAbstractClass( 'Carbon_Fields\Field\Field', array(), '', false );
}
public function tearDown(): void {
unset( $this->field );
}
/**
* @covers ::get_id
* @covers ::set_id
*/
public function testGetSetId() {
$expected = mt_rand();
$this->field->set_id( $expected );
$this->assertSame( $expected, $this->field->get_id() );
}
}

View file

@ -0,0 +1,215 @@
<?php
use Carbon_Fields\Field\Field;
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
/**
* @group field
* @coversDefaultClass Carbon_Fields\Field\Field
*/
class FieldInitializationTest extends WP_UnitTestCase {
public $fieldName;
public function setUp(): void {
$this->fieldName = '_color';
}
public function tearDown(): void {
// This is required just to overwrite code in WP_UnitTestCase
// that accesses the database
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
* @covers ::get_name
* @covers ::set_name
*/
public function testMakeTextFields() {
$field = Field::make( 'text', $this->fieldName );
$this->assertSame( $this->fieldName, $field->get_name() );
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
*/
public function testExceptionIsThrownWhenFieldTypeIsEmpty() {
$field = Field::make( '', $this->fieldName );
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
*/
public function testExceptionIsThrownWhenFieldTypeIsInvalid() {
$field = Field::make( '__no_such_field_type__', $this->fieldName );
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
*/
public function testBrokenFieldIsReturnedWhenDebugIsDisabledAndFieldIsInvalid() {
$old_val = Incorrect_Syntax_Exception::$throw_errors;
Incorrect_Syntax_Exception::$throw_errors = false;
$field = Field::make( '__no_such_field_type__', $this->fieldName );
$this->assertInstanceOf( 'Carbon_Fields\Field\Broken_Field', $field );
Incorrect_Syntax_Exception::$throw_errors = $old_val;
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
*/
public function testDashIsNotAllowedInFieldType() {
$field = Field::make( 'gravity-form', $this->fieldName );
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
*/
public function testFieldTypeCaseIsIgnored() {
$field = Field::make( 'Text', $this->fieldName );
$this->assertInstanceOf( 'Carbon_Fields\Field\Text_Field', $field );
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
*/
public function testSpacesInFieldTypeAreSupported() {
$field = Field::make( 'Gravity Form', $this->fieldName );
$this->assertTrue( true ); // no exception ...
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
* @covers ::get_name
* @covers ::set_name
*/
public function testFieldNameIsPrependedWithUnderscoreAutomatically() {
$field = Field::make( 'text', 'something' );
$this->assertSame( '_something', $field->get_name() );
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
* @covers ::get_name
* @covers ::set_name
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
*/
public function testFieldNameThrowsExceptionOnUpperCaseValues() {
$field = Field::make( 'text', 'UPPER_CASE_FIELD_NAME' );
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
* @covers ::set_name
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
*/
public function testFieldNameThrowsExceptionOnNonEnglishWordCharacters() {
$field = Field::make( 'text', '## Even a weirder | name! :)' );
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
* @covers ::get_name
* @covers ::set_name
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
*/
public function testFieldNameThrowsExceptionOnUnicodeValues() {
$field = Field::make( 'text', 'bulgarian; България' );
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
*/
public function testLabelIsSetupProperlyWhenPassedExplicitly() {
$field = Field::make( 'text', 'color', "Field Color" );
$this->assertSame( "Field Color", $field->get_label() );
// Make sure that non-UTF8 labels are properlly supported
$field = Field::make( 'text', 'color', "Цвят" );
$this->assertSame( "Цвят", $field->get_label() );
// Derive the label in proper case
$field = Field::make( 'text', 'color_of_something' );
$this->assertSame( "Color Of Something", $field->get_label() );
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
*/
public function testLabelIsDerivedProperly() {
$field = Field::make( 'text', 'field_color' );
$this->assertSame( "Field Color", $field->get_label() );
$field = Field::make( 'text', '_field_color' );
$this->assertSame( "Field Color", $field->get_label() );
$field = Field::make( 'text', 'crb_field_color' );
$this->assertSame( "Field Color", $field->get_label() );
$field = Field::make('text', '_crb_field_color' );
$this->assertSame( "Field Color", $field->get_label() );
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
* @covers ::set_name
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage can only contain lowercase alphanumeric characters
*/
public function testFieldNameCantBeEmpty() {
Field::make( 'text', '' );
}
/**
* @covers ::make
* @covers ::factory
* @covers ::__construct
* @covers ::set_name
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage can only contain lowercase alphanumeric characters
*/
public function testFieldNameCantContainHiddenlySupportedBrackets() {
Field::make( 'text', 'test_field_with_[brackets]' );
}
}

View file

@ -0,0 +1,148 @@
<?php
use Mockery as M;
use Carbon_Fields\Value_Set\Value_Set;
/**
* @group field
* @coversDefaultClass Carbon_Fields\Field\Field
*/
class FieldLoadSaveTest extends WP_UnitTestCase {
public $subject;
public $datastore;
public function setUp(): void {
$this->subject = M::mock( 'Carbon_Fields\Field\Field' )->makePartial();
$this->subject->set_base_name( 'carbon_field' );
$this->subject->set_name( 'carbon_field' );
$this->subject->set_label( 'Carbon Field' );
$this->datastore = M::mock( 'Carbon_Fields\Datastore\Datastore_Interface' );
}
public function tearDown(): void {
M::close();
unset( $this->subject );
unset( $this->datastore );
}
/**
* @covers ::set_datastore
* @covers ::get_datastore
*/
public function testGetDatastoreReturnsPreviouslySetDatastore() {
$this->subject->set_datastore( $this->datastore );
$this->assertSame( $this->datastore, $this->subject->get_datastore() );
}
/**
* @covers ::set_default_value
* @covers ::get_default_value
*/
public function testGetDefaultValueReturnsPreviouslySetDefaultValue() {
$expected = 'test default value';
$this->subject->set_default_value( $expected );
$this->assertSame( $expected, $this->subject->get_default_value() );
}
/**
* @covers ::set_value
* @covers ::get_value
*/
public function testGetValueReturnsPreviouslySetValue() {
$expected = 'test value';
$this->subject->set_value( $expected );
$this->assertSame( $expected, $this->subject->get_value() );
}
/**
* @covers ::load
* @covers ::get_value
*/
public function testLoadAppliesDefaultValueWhenDatastoreReturnsNull() {
$expected = 'test default value';
$this->datastore->shouldReceive( 'load' )->andReturn( null )->once();
$this->subject->set_datastore( $this->datastore );
$this->subject->set_default_value( $expected );
$this->assertSame( $expected, $this->subject->get_value() );
$this->subject->load();
$this->assertSame( $expected, $this->subject->get_value() );
}
/**
* @covers ::load
* @covers ::get_value
*/
public function testLoadAppliesTheSameValueWhenDatastoreReturnsValue() {
$expected = 'test value from datastore';
$this->datastore->shouldReceive( 'load' )->andReturn( array(
array(
Value_Set::VALUE_PROPERTY => $expected,
),
) )->once();
$this->subject->set_datastore( $this->datastore );
$this->subject->load();
$this->assertSame( $expected, $this->subject->get_value() );
}
/**
* @covers ::save
*/
public function testSavePassesFieldToDatastore() {
$this->datastore->shouldReceive( 'save' )->once();
$this->subject->shouldReceive( 'delete' )->once();
$this->subject->set_datastore( $this->datastore );
$this->subject->save();
$this->assertTrue( true ); // rely on Mockery expectations to fail the test
}
/**
* @covers ::delete
*/
public function testDeletePassesFieldToDatastore() {
$this->datastore->shouldReceive( 'delete' )->once();
$this->subject->set_datastore( $this->datastore );
$this->subject->delete();
$this->assertTrue( true ); // rely on Mockery expectations to fail the test
}
/**
* @covers ::set_value_from_input
*/
public function testSetValueFromInputTakesValue() {
$expected = 'test value from input';
$input = array( '_carbon_field' => $expected );
$this->subject->set_value_from_input( $input );
$this->assertSame( $expected, $this->subject->get_value() );
}
/**
* @covers ::set_value_from_input
*/
public function testSetValueFromInputSetsEmptyValueWhenMissingFromInput() {
$expected = 'test value from input';
$input = array( );
$this->subject->set_value_from_input( $input );
$this->assertSame( '', $this->subject->get_value() );
}
/**
* @covers ::get_formatted_value
*/
public function testGetFormattedValueReturnsValue() {
$expected = 'test value from input';
$this->subject->set_value( $expected );
$this->assertSame( $expected, $this->subject->get_formatted_value() );
}
/**
* @covers ::get_formatted_value
*/
public function testGetFormattedValueReturnsDefaultValue() {
$expected = 'test value from input';
$this->subject->set_default_value( $expected );
$this->assertSame( $expected, $this->subject->get_formatted_value() );
}
}

View file

@ -0,0 +1,48 @@
<?php
use Mockery as M;
use Carbon_Fields\Field\Map_Field;
use Carbon_Fields\Value_Set\Value_Set;
/**
* @group field
* @coversDefaultClass Carbon_Fields\Field\Map_Field
*/
class MapFieldTest extends WP_UnitTestCase {
public $subject;
public function setUp(): void {
$this->subject = M::mock( 'Carbon_Fields\Field\Map_Field' )->makePartial();
}
public function tearDown(): void {
M::close();
unset( $this->subject );
}
/**
* @covers ::set_position
*/
public function testSetPositionUpdatesDefaultValue() {
$clean = array(
Value_Set::VALUE_PROPERTY => '',
'lat' => 0,
'lng' => 0,
'zoom' => 0,
'address' => '',
);
$expected = array(
Value_Set::VALUE_PROPERTY => '40.346544,-101.645507',
'lat' => 40.346544,
'lng' => -101.645507,
'zoom' => 10,
'address' => '',
);
$this->subject->set_position( $clean['lat'], $clean['lng'], $clean['zoom'] );
$this->assertSame( $clean, $this->subject->get_default_value() );
$this->subject->set_position( $expected['lat'], $expected['lng'], $expected['zoom'] );
$this->assertSame( $expected, $this->subject->get_default_value() );
}
}

View file

@ -0,0 +1,160 @@
<?php
use Mockery as M;
use Carbon_Fields\Pimple\Container as PimpleContainer;
use Carbon_Fields\Container\Repository as ContainerRepository;
use Carbon_Fields\Toolset\Key_Toolset;
use Carbon_Fields\Value_Set\Value_Set;
use Carbon_Fields\Container\Condition\Factory as ConditionFactory;
/**
* @group field
* @coversDefaultClass Carbon_Fields\Field\Field
*/
class MiscTest extends WP_UnitTestCase {
public $text_field;
public $set_field;
public $complex_field;
public $container;
public function setUp(): void {
$ioc = new PimpleContainer();
$ioc['container_repository'] = function( $ioc ) {
return new ContainerRepository();
};
$ioc['key_toolset'] = function() {
return new Key_Toolset();
};
$ioc['container_condition_factory'] = function( $ioc ) {
return new ConditionFactory( $ioc['container_conditions'] );
};
$ioc['container_condition_translator_array'] = function( $ioc ) {
return new \Carbon_Fields\Container\Fulfillable\Translator\Array_Translator( $ioc['container_condition_factory'] );
};
$ioc['container_condition_translator_json'] = function( $ioc ) {
return new \Carbon_Fields\Container\Fulfillable\Translator\Json_Translator( $ioc['container_condition_factory'] );
};
$ioc['container_condition_fulfillable_collection'] = $ioc->factory( function( $ioc ) {
return M::mock( 'Carbon_Fields\\Container\\Fulfillable\\Fulfillable_Collection' )->shouldIgnoreMissing();
} );
$ioc['container_conditions'] = function() {
return new PimpleContainer();
};
\Carbon_Fields\Carbon_Fields::instance()->install( $ioc );
$this->text_field = Carbon_Fields\Field::make( 'text', 'text_field' );
$this->set_field = Carbon_Fields\Field::make( 'set', 'set_field' );
$this->complex_field = Carbon_Fields\Field::make( 'complex', 'complex_field' );
$this->container = Carbon_Fields\Container::make( 'theme_options', 'Theme Options' );
}
public function tearDown(): void {
M::close();
unset( $this->text_field );
unset( $this->set_field );
unset( $this->complex_field );
unset( $this->container );
}
/**
* @covers ::is_simple_root_field
*/
public function testIsSimpleRootFieldForUnassignedFields() {
$this->assertSame( true, $this->text_field->is_simple_root_field() );
$this->assertSame( false, $this->set_field->is_simple_root_field() );
$this->assertSame( false, $this->complex_field->is_simple_root_field() );
}
/**
* @covers ::is_simple_root_field
*/
public function testIsSimpleRootFieldForRootFields() {
$this->container->add_fields( array(
$this->text_field,
$this->set_field,
$this->complex_field,
) );
$this->assertSame( true, $this->text_field->is_simple_root_field() );
$this->assertSame( false, $this->set_field->is_simple_root_field() );
$this->assertSame( false, $this->complex_field->is_simple_root_field() );
}
/**
* @covers ::is_simple_root_field
*/
public function testIsSimpleRootFieldForNestedFields() {
$parent_field = Carbon_Fields\Field::make( 'complex', 'parent_field' );
$parent_field->add_fields( array(
$this->text_field,
$this->set_field,
$this->complex_field,
) );
$this->container->add_fields( array(
$parent_field,
) );
$this->assertSame( false, $this->text_field->is_simple_root_field() );
$this->assertSame( false, $this->set_field->is_simple_root_field() );
$this->assertSame( false, $this->complex_field->is_simple_root_field() );
}
/**
* @covers ::get_value_set
*/
public function testGetValueSetReturnsDefaultValueSet() {
$default_value_set = new Value_Set();
$this->assertSame( $default_value_set->get_type(), $this->text_field->get_value_set()->get_type() );
}
/**
* @covers ::get_value_set
* @covers ::set_value_set
*/
public function testSetValueSetOverridesValueSet() {
$expected = new Value_Set( Value_Set::TYPE_MULTIPLE_VALUES );
$this->text_field->set_value_set( $expected );
$this->assertSame( $expected, $this->text_field->get_value_set() );
}
/**
* @covers ::get_name_prefix
* @covers ::set_name_prefix
*/
public function testSetNamePrefixChangesFieldNameWithEmptyPrefix() {
$prefix = '';
$expected = $prefix . 'text_field';
$this->text_field->set_name_prefix( $prefix );
$this->assertSame( $expected, $this->text_field->get_name() );
}
/**
* @covers ::get_name_prefix
* @covers ::set_name_prefix
*/
public function testSetNamePrefixChangesFieldName() {
$prefix = '_zzz_';
$expected = $prefix . 'text_field';
$this->text_field->set_name_prefix( $prefix );
$this->assertSame( $expected, $this->text_field->get_name() );
}
/**
* @covers ::get_name_prefix
* @covers ::set_name_prefix
*/
public function testSetNamePrefixChangesFieldNameAfterSeveralChanges() {
$prefixes = array( 'test1_', 2, 'test3_' );
foreach ( $prefixes as $prefix ) {
$this->text_field->set_name_prefix( $prefix );
}
$expected = $prefixes[ count( $prefixes ) - 1 ] . 'text_field';
$this->assertSame( $expected, $this->text_field->get_name() );
}
}

View file

@ -0,0 +1,294 @@
<?php
use Mockery as M;
use Carbon_Fields\Field\Predefined_Options_Field;
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
/**
* @group field
* @coversDefaultClass Carbon_Fields\Field\Predefined_Options_Field
*/
class PredefinedOptionsFieldTest extends WP_UnitTestCase {
public $subject;
public function setUp(): void {
$this->subject = M::mock( 'Carbon_Fields\Field\Predefined_Options_Field' )->makePartial();
}
public function tearDown(): void {
M::close();
unset( $this->subject );
}
/**
* @covers ::set_options
* @covers ::get_options
*/
public function testSetAndGetOptions() {
$expected = array(1, 2, 3);
$this->subject->set_options( $expected );
$this->assertSame( $expected, $this->subject->get_options() );
}
/**
* @covers ::set_options
* @covers ::get_options
*/
public function testSetOptionsResetsPreviousOnes() {
$this->subject->set_options( array(1, 2, 3) );
$expected = array(4, 5, 6);
$this->subject->set_options( $expected );
$this->assertSame( $expected, $this->subject->get_options() );
}
/**
* @covers ::set_options
* @covers ::get_options
*/
public function testSetEmptyArrayWillDeleteExistingOptions() {
$this->subject->set_options( array(1, 2, 3) );
$expected = array();
$this->subject->set_options( $expected );
$this->assertSame( $expected, $this->subject->get_options() );
}
/**
* @covers ::set_options
* @covers ::get_options
*/
public function testSetOptionsCallable() {
$expected = array(1, 2, 3);
$callback = function() use ( $expected ) {
return $expected;
};
$this->subject->set_options( $callback );
$this->assertSame( $expected, $this->subject->get_options() );
}
/**
* @covers ::set_options
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage Only arrays and callbacks are allowed in the <code>set_options()</code> method.
*/
public function testSetOptionsString() {
$this->subject->set_options( 'foo' );
}
/**
* @covers ::set_options
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage Only arrays and callbacks are allowed in the <code>set_options()</code> method.
*/
public function testSetOptionsInteger() {
$this->subject->set_options( 123 );
}
/**
* @covers ::set_options
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage Only arrays and callbacks are allowed in the <code>set_options()</code> method.
*/
public function testSetOptionsBool() {
$this->subject->set_options( false );
}
/**
* @covers ::set_options
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage Only arrays and callbacks are allowed in the <code>set_options()</code> method.
*/
public function testSetOptionsObject() {
$this->subject->set_options( M::mock( 'stdClass' ) );
}
/**
* @covers ::add_options
* @covers ::get_options
*/
public function testAddOptionsArray() {
$expected = array('foo', 'bar');
$this->subject->add_options( $expected );
$this->assertSame( $expected, $this->subject->get_options() );
}
/**
* @covers ::add_options
* @covers ::get_options
*/
public function testAddOptionsArrayPreservesOtherOptions() {
$options_1 = array( 'foo', 'bar' );
$options_2 = array( 'foobar', 'barfoo' );
$expected = array( 'foo', 'bar', 'foobar', 'barfoo' );
$this->subject->add_options( $options_1 );
$this->subject->add_options( $options_2 );
$this->assertSame( $expected, $this->subject->get_options() );
}
/**
* @covers ::add_options
* @covers ::get_options
*/
public function testAddOptionsArrayWithAssociativeArray() {
$options_1 = array( 'foo' => 'bar', 'bar' => 'foo' );
$options_2 = array( 'foobar' => 'barfoo', 'bar' => 'barbar' );
$expected = array( 'foo' => 'bar', 'bar' => 'foo', 'foobar' => 'barfoo', 'bar' => 'barbar' );
$this->subject->add_options( $options_1 );
$this->subject->add_options( $options_2 );
$this->assertSame( $expected, $this->subject->get_options() );
}
/**
* @covers ::add_options
* @covers ::get_options
*/
public function testAddOptionsArraysWithNumericAssociativeArrays() {
$options_1 = array( 3 => 'Option 1' );
$options_2 = array( 9 => 'Option 2' );
$expected = array( 3 => 'Option 1', 9 => 'Option 2' );
$this->subject->add_options( $options_1 );
$this->subject->add_options( $options_2 );
$this->assertSame( $expected, $this->subject->get_options() );
}
/**
* @covers ::add_options
* @covers ::get_options
*/
public function testAddOptionsArraysWithMixedAssociativeArrays() {
$options_1 = array( 0 => 'Option 1' );
$options_2 = array( 'foo' => 'Option 2' );
$options_3 = array( 1 => 'Option 3' );
$expected = array( 0 => 'Option 1', 'foo' => 'Option 2', 1 => 'Option 3' );
$this->subject->add_options( $options_1 );
$this->subject->add_options( $options_2 );
$this->subject->add_options( $options_3 );
$this->assertSame( $expected, $this->subject->get_options() );
}
/**
* Possibly a duplicate of other tests but kept for its readability
*
* @covers ::add_options
* @covers ::get_options
*/
public function testAddOptionsArraysReindex() {
$options_1 = array( 0 => 'Option 1' );
$options_2 = array( 0 => 'Option 2' );
$expected = array( 0 => 'Option 1', 1 => 'Option 2' );
$this->subject->add_options( $options_1 );
$this->subject->add_options( $options_2 );
$this->assertSame( $expected, $this->subject->get_options() );
}
/**
* @covers ::add_options
* @covers ::get_options
*/
public function testAddOptionsArraysAppend() {
$options_1 = array( 0 => 'Option 1', 1 => 'Option 2' );
$options_2 = array( 9 => 'Option 3' );
$expected = array( 0 => 'Option 1', 1 => 'Option 2', 9 => 'Option 3' );
$this->subject->add_options( $options_1 );
$this->subject->add_options( $options_2 );
$this->assertSame( $expected, $this->subject->get_options() );
}
/**
* @covers ::add_options
* @covers ::get_options
*/
public function testAddOptionsArraysOverwrite() {
$options_1 = array( 0 => 'Option 1' );
$options_2 = array( 9 => 'Option 2' );
$options_3 = array( 0 => 'Option 3' );
$expected = array( 0 => 'Option 3', 9 => 'Option 2' );
$this->subject->add_options( $options_1 );
$this->subject->add_options( $options_2 );
$this->subject->add_options( $options_3 );
$this->assertSame( $expected, $this->subject->get_options() );
}
/**
* @covers ::set_options
* @covers ::add_options
* @covers ::get_options
*/
public function testAddOptionsArrayAfterCallable() {
$base = array( 1, 2, 3 );
$added = array( 4, 5, 6 );
$expected = array( 1, 2, 3, 4, 5, 6 );
$this->subject->set_options( function() use ( $base ) {
return $base;
} );
$this->subject->add_options( $added );
$this->assertSame( $expected, $this->subject->get_options() );
}
/**
* @covers ::add_options
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage Only arrays and callbacks are allowed in the <code>add_options()</code> method.
*/
public function testAddOptionsString() {
$this->subject->add_options( 'foo' );
}
/**
* @covers ::add_options
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage Only arrays and callbacks are allowed in the <code>add_options()</code> method.
*/
public function testAddOptionsInteger() {
$this->subject->add_options( 123 );
}
/**
* @covers ::add_options
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage Only arrays and callbacks are allowed in the <code>add_options()</code> method.
*/
public function testAddOptionsBool() {
$this->subject->add_options( false );
}
/**
* @covers ::add_options
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
* @expectedExceptionMessage Only arrays and callbacks are allowed in the <code>add_options()</code> method.
*/
public function testAddOptionsObject() {
$this->subject->add_options( M::mock( 'stdClass' ) );
}
}

View file

@ -0,0 +1,75 @@
<?php
use Mockery as M;
use Carbon_Fields\Helper\Color;
/**
* @group helper
* @coversDefaultClass Carbon_Fields\Helper\Color
*/
class ColorTest extends WP_UnitTestCase {
public $rgba_solid;
public $rgba_transparent;
public function setUp(): void {
$this->rgba_solid = array(
'red' => 17,
'green' => 34,
'blue' => 51,
'alpha' => 1,
);
$this->rgba_transparent = array(
'red' => 17,
'green' => 34,
'blue' => 51,
'alpha' => 0,
);
}
public function tearDown(): void {
M::close();
}
/**
* @covers ::hex_to_rgba
*/
public function testHexToRgba_ParsesHex() {
$expected = $this->rgba_solid;
$hex = '#112233FF';
$this->assertEquals( $expected, Color::hex_to_rgba( $hex ) );
}
/**
* @covers ::hex_to_rgba
*/
public function testHexToRgba_WithoutAlpha_DefaultsToMaxAlpha() {
$expected = $this->rgba_solid;
$without_alpha = '#112233';
$this->assertEquals( $expected, Color::hex_to_rgba( $without_alpha ) );
}
/**
* @covers ::hex_to_rgba
*/
public function testHexToRgba_WithAlpha_ReadsAlphaValue() {
$expected = $this->rgba_transparent;
$transparent = '#11223300';
$this->assertEquals( $expected, Color::hex_to_rgba( $transparent ) );
}
/**
* @covers ::hex_to_rgba
*/
public function testHexToRgba_IgnoresLeadingNumberSign() {
$expected = $this->rgba_solid;
$with_number_sign = '#112233FF';
$without_number_sign = '112233FF';
$this->assertEquals( $expected, Color::hex_to_rgba( $with_number_sign ) );
$this->assertEquals( $expected, Color::hex_to_rgba( $without_number_sign ) );
}
}

View file

@ -0,0 +1,500 @@
<?php
use Mockery as M;
use Carbon_Fields\Toolset\Key_Toolset;
use Carbon_Fields\Value_Set\Value_Set;
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
/**
* @coversDefaultClass Carbon_Fields\Toolset\Key_Toolset
*/
class KeyToolsetTest extends WP_UnitTestCase {
public $subject;
protected $connected_to_db = false;
public function setUp(): void {
global $wpdb;
if ( ! $this->connected_to_db ) {
$this->connected_to_db = $wpdb->db_connect();
}
$this->subject = new Key_Toolset();
}
public function tearDown(): void {
global $wpdb;
M::close();
unset( $this->subject );
if ( $this->connected_to_db && is_callable( array( $wpdb, 'close' ) ) ) {
$wpdb->close();
}
}
/**
* @covers ::get_sanitized_hierarchy_index
*/
public function testGetSanitizedHierarchyIndexCutsOffExtraValues() {
$full_hierarchy = array( 'field', 'field', 'field', 'field', 'field', 'field' );
$full_hierarchy_index = array( 1, 2, 3, 4, 5, 6 );
$expected = array( 1, 2, 3, 4, 5 );
$this->assertSame( $expected, $this->subject->get_sanitized_hierarchy_index( $full_hierarchy, $full_hierarchy_index ) );
}
/**
* @covers ::get_sanitized_hierarchy_index
*/
public function testGetSanitizedHierarchyIndexIgnoresTheLastField() {
$full_hierarchy = array( 'field', 'field' );
$full_hierarchy_index = array( 1, 2 );
$expected = array( 1 );
$this->assertSame( $expected, $this->subject->get_sanitized_hierarchy_index( $full_hierarchy, $full_hierarchy_index ) );
}
/**
* @covers ::get_sanitized_hierarchy_index
*/
public function testGetSanitizedHierarchyIndexEnsuresIntegerValues() {
$full_hierarchy = array( 'field', 'field' );
$full_hierarchy_index = array( '1' );
$expected = array( 1 );
$this->assertSame( $expected, $this->subject->get_sanitized_hierarchy_index( $full_hierarchy, $full_hierarchy_index ) );
}
/**
* @covers ::get_storage_key
*/
public function testGetStorageKeyReturnsSimpleRootKeyForSimpleRootField() {
$expected = '_field';
$received = $this->subject->get_storage_key(
true,
array( 'field' ),
array( 0 ),
0,
Value_Set::VALUE_PROPERTY
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key
*/
public function testGetStorageKeyReturnsSimpleRootKeyForSimpleRootFieldDiscardingExtraInfo() {
$expected = '_field';
$received = $this->subject->get_storage_key(
true,
array( 'field', 'foo', 'bar' ),
array( 9, 99, 1, 2, 3 ), // added junk
999,
Value_Set::VALUE_PROPERTY
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key
*/
public function testGetStorageKeyReturnsComplexKeyForSimpleRootFieldWithCustomProperty() {
$expected = '_field|foo:bar|9:99|999|some_property_name';
$received = $this->subject->get_storage_key(
true,
array( 'field', 'foo', 'bar' ),
array( 9, 99 ),
999,
'some_property_name'
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key
*/
public function testGetStorageKeyReturnsComplexKeyForRootField() {
$expected = '_field|||999|' . Value_Set::VALUE_PROPERTY;
$received = $this->subject->get_storage_key(
false,
array( 'field' ),
array( 1, 2, 3 ), // added junk
999,
Value_Set::VALUE_PROPERTY
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key
*/
public function testGetStorageKeyReturnsComplexKeyForFieldWithDefaultProperty() {
$expected = '_field|foo:bar|9:99|999|' . Value_Set::VALUE_PROPERTY;
$received = $this->subject->get_storage_key(
false,
array( 'field', 'foo', 'bar' ),
array( 9, 99 ),
999,
Value_Set::VALUE_PROPERTY
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key
*/
public function testGetStorageKeyReturnsComplexKeyForFieldWithCustomProperty() {
$expected = '_field|foo:bar|9:99|999|some_property_name';
$received = $this->subject->get_storage_key(
false,
array( 'field', 'foo', 'bar' ),
array( 9, 99 ),
999,
'some_property_name'
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key_with_index_wildcards
*/
public function testGetStorageKeyWithIndexWildcardsReturnsSimpleRootKeyForSimpleRootField() {
$expected = '_field';
$received = $this->subject->get_storage_key_with_index_wildcards(
true,
array( 'field', 'foo', 'bar' )
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key_with_index_wildcards
*/
public function testGetStorageKeyWithIndexWildcardsReturnsComplexKeyForRootField() {
$expected = '_field|||%|' . Value_Set::VALUE_PROPERTY;
$received = $this->subject->get_storage_key_with_index_wildcards(
false,
array( 'field' ),
Value_Set::VALUE_PROPERTY,
'%'
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key_with_index_wildcards
*/
public function testGetStorageKeyWithIndexWildcardsReturnsComplexKeyForNestedField() {
$expected = '_field|foo:bar|%|%|' . Value_Set::VALUE_PROPERTY;
$received = $this->subject->get_storage_key_with_index_wildcards(
false,
array( 'field', 'foo', 'bar' ),
Value_Set::VALUE_PROPERTY,
'%'
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key_getter_patterns
*/
public function testGetStorageKeyGetterPatternsForSimpleRootField() {
$expected = array(
'_field' => Key_Toolset::PATTERN_COMPARISON_EQUAL,
'_field|' => Key_Toolset::PATTERN_COMPARISON_STARTS_WITH,
);
$received = $this->subject->get_storage_key_getter_patterns(
true,
array( 'field' )
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key_getter_patterns
*/
public function testGetStorageKeyGetterPatternsForRootField() {
$expected = array(
'_field|' => Key_Toolset::PATTERN_COMPARISON_STARTS_WITH,
);
$received = $this->subject->get_storage_key_getter_patterns(
false,
array( 'field' )
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key_getter_patterns
*/
public function testGetStorageKeyGetterPatternsForNestedField() {
$expected = array(
'_field|foo:bar|' => Key_Toolset::PATTERN_COMPARISON_STARTS_WITH,
'_field|foo:bar:' => Key_Toolset::PATTERN_COMPARISON_STARTS_WITH,
);
$received = $this->subject->get_storage_key_getter_patterns(
false,
array( 'field', 'foo', 'bar' )
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key_deleter_patterns
*/
public function testGetStorageKeyDeleterPatternsForSimpleRootField() {
$expected = array(
'_field' => Key_Toolset::PATTERN_COMPARISON_EQUAL,
'_field|||' => Key_Toolset::PATTERN_COMPARISON_STARTS_WITH,
);
$received = $this->subject->get_storage_key_deleter_patterns(
false,
true,
array( 'field' ),
array( 0 )
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key_deleter_patterns
*/
public function testGetStorageKeyDeleterPatternsForNestedField() {
$expected = array(
'_field|foo:bar|1:2|' => Key_Toolset::PATTERN_COMPARISON_STARTS_WITH,
);
$received = $this->subject->get_storage_key_deleter_patterns(
false,
false,
array( 'field', 'foo', 'bar' ),
array( 1, 2 )
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key_deleter_patterns
*/
public function testGetStorageKeyDeleterPatternsForComplexRootField() {
$expected = array(
'_field|' => Key_Toolset::PATTERN_COMPARISON_STARTS_WITH,
);
$received = $this->subject->get_storage_key_deleter_patterns(
true,
false,
array( 'field' ),
array( 0 )
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_key_deleter_patterns
*/
public function testGetStorageKeyDeleterPatternsForComplexNestedField() {
$expected = array(
'_field|' => Key_Toolset::PATTERN_COMPARISON_STARTS_WITH,
);
$received = $this->subject->get_storage_key_deleter_patterns(
true,
false,
array( 'field', 'foo', 'bar' ),
array( 1, 2 )
);
$this->assertSame( $expected, $received );
}
/**
* @covers ::storage_key_patterns_to_sql
*/
public function testStorageKeyPatternsToSql() {
$table_column = '`option_name`';
$patterns = array(
'_field' => Key_Toolset::PATTERN_COMPARISON_EQUAL,
'_field|' => Key_Toolset::PATTERN_COMPARISON_STARTS_WITH,
);
$expected = ' ( `option_name` = "_field" OR `option_name` LIKE "\_field|%" ) ';
$received = $this->subject->storage_key_patterns_to_sql( $table_column, $patterns );
$this->assertSame( $expected, $received );
}
/**
* @covers ::storage_key_patterns_to_sql
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
*/
public function testStorageKeyPatternsToSqlThrowsExceptionOnInvalidComparison() {
$table_column = '`option_name`';
$patterns = array(
'_field' => 'non_existant_comparison_type',
);
$this->subject->storage_key_patterns_to_sql( $table_column, $patterns );
}
/**
* @covers ::storage_key_matches_any_pattern
*/
public function testStorageKeyMatchesAnyPatternEqualComparisonTrue() {
$storage_key = '_field';
$patterns = array(
'_field' => Key_Toolset::PATTERN_COMPARISON_EQUAL,
);
$this->assertSame( true, $this->subject->storage_key_matches_any_pattern( $storage_key, $patterns ) );
}
/**
* @covers ::storage_key_matches_any_pattern
*/
public function testStorageKeyMatchesAnyPatternEqualComparisonFalse() {
$storage_key = '_field';
$patterns = array(
'_different_field' => Key_Toolset::PATTERN_COMPARISON_EQUAL,
);
$this->assertSame( false, $this->subject->storage_key_matches_any_pattern( $storage_key, $patterns ) );
}
/**
* @covers ::storage_key_matches_any_pattern
*/
public function testStorageKeyMatchesAnyPatternStartsWithComparisonTrue() {
$storage_key = '_field|child_field';
$patterns = array(
'_field|' => Key_Toolset::PATTERN_COMPARISON_STARTS_WITH,
);
$this->assertSame( true, $this->subject->storage_key_matches_any_pattern( $storage_key, $patterns ) );
}
/**
* @covers ::storage_key_matches_any_pattern
*/
public function testStorageKeyMatchesAnyPatternStartsWithComparisonFalse() {
$storage_key = '_field|child_field';
$patterns = array(
'_different_field|' => Key_Toolset::PATTERN_COMPARISON_STARTS_WITH,
);
$this->assertSame( false, $this->subject->storage_key_matches_any_pattern( $storage_key, $patterns ) );
}
/**
* @covers ::storage_key_matches_any_pattern
*/
public function testStorageKeyMatchesAnyPatternMixedComparisonTrue() {
$storage_key = '_field|child_field';
$patterns = array(
'_field|child_field' => Key_Toolset::PATTERN_COMPARISON_EQUAL,
'_field|' => Key_Toolset::PATTERN_COMPARISON_STARTS_WITH,
);
$this->assertSame( true, $this->subject->storage_key_matches_any_pattern( $storage_key, $patterns ) );
}
/**
* @covers ::storage_key_matches_any_pattern
*/
public function testStorageKeyMatchesAnyPatternMixedComparisonTrueForSecond() {
$storage_key = '_field|child_field';
$patterns = array(
'_field' => Key_Toolset::PATTERN_COMPARISON_EQUAL,
'_field|child_field' => Key_Toolset::PATTERN_COMPARISON_EQUAL,
);
$this->assertSame( true, $this->subject->storage_key_matches_any_pattern( $storage_key, $patterns ) );
}
/**
* @covers ::storage_key_matches_any_pattern
*/
public function testStorageKeyMatchesAnyPatternMixedComparisonFalse() {
$storage_key = '_field|child_field';
$patterns = array(
'_different_field|child_field' => Key_Toolset::PATTERN_COMPARISON_EQUAL,
'_different_field|' => Key_Toolset::PATTERN_COMPARISON_STARTS_WITH,
);
$this->assertSame( false, $this->subject->storage_key_matches_any_pattern( $storage_key, $patterns ) );
}
/**
* @covers ::storage_key_matches_any_pattern
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
*/
public function testStorageKeyMatchesAnyPatternThrowsExceptionOnInvalidComparison() {
$storage_key = '_field';
$patterns = array(
'_field' => 'non_existant_comparison_type',
);
$this->subject->storage_key_matches_any_pattern( $storage_key, $patterns );
}
/**
* @covers ::is_segments_array_full
*/
public function testIsSegmentsArrayFull() {
$partial_segments = array( 'segment' );
$this->assertSame( false, $this->subject->is_segments_array_full( $partial_segments ) );
$full_segments = array( 'segment', 'segment', 'segment', 'segment', 'segment' );
$this->assertSame( true, $this->subject->is_segments_array_full( $full_segments ) );
}
/**
* @covers ::storage_key_to_segments_array
*/
public function testStorageKeyToSegmentsArray() {
$storage_key = '_field|foo:bar|0|1|' . Value_Set::VALUE_PROPERTY;
$expected = array( 'field', 'foo:bar', '0', '1', Value_Set::VALUE_PROPERTY );
$this->assertSame( $expected, $this->subject->storage_key_to_segments_array( $storage_key ) );
}
/**
* @covers ::segment_to_segment_values_array
*/
public function testSegmentToSegmentValuesArray() {
$storage_key = 'foo:bar:baz';
$expected = array( 'foo', 'bar', 'baz' );
$this->assertSame( $expected, $this->subject->segment_to_segment_values_array( $storage_key ) );
}
/**
* @covers ::parse_storage_key
*/
public function testParseStorageKeySimpleRootKey() {
$storage_key = '_field';
$expected = array(
'root' => 'field',
'hierarchy' => array(),
'hierarchy_index' => array(),
'value_index' => 0,
'property' => Value_Set::VALUE_PROPERTY,
'full_hierarchy' => array( 'field' ),
);
$this->assertSame( $expected, $this->subject->parse_storage_key( $storage_key ) );
}
/**
* @covers ::parse_storage_key
*/
public function testParseStorageKeyComplexRootKey() {
$storage_key = '_field||1|2|some_property_name';
$expected = array(
'root' => 'field',
'hierarchy' => array(),
'hierarchy_index' => array( 1 ),
'value_index' => 2,
'property' => 'some_property_name',
'full_hierarchy' => array( 'field' ),
);
$this->assertSame( $expected, $this->subject->parse_storage_key( $storage_key ) );
}
/**
* @covers ::parse_storage_key
*/
public function testParseStorageKeyNestedKey() {
$storage_key = '_field|foo:bar|1:2|3|some_property_name';
$expected = array(
'root' => 'field',
'hierarchy' => array( 'foo', 'bar' ),
'hierarchy_index' => array( 1, 2 ),
'value_index' => 3,
'property' => 'some_property_name',
'full_hierarchy' => array( 'field', 'foo', 'bar' ),
);
$this->assertSame( $expected, $this->subject->parse_storage_key( $storage_key ) );
}
}

View file

@ -0,0 +1,210 @@
<?php
use Mockery as M;
use Carbon_Fields\Pimple\Container as PimpleContainer;
use Carbon_Fields\Container\Repository as ContainerRepository;
use Carbon_Fields\Field\Field;
use Carbon_Fields\Service\Legacy_Storage_Service_v_1_5;
use Carbon_Fields\Toolset\Key_Toolset;
use Carbon_Fields\Toolset\WP_Toolset;
use Carbon_Fields\Container\Condition\Factory as ConditionFactory;
/**
* @coversDefaultClass Carbon_Fields\Service\Legacy_Storage_Service_v_1_5
*/
class LegacyStorageServicev15Test extends WP_UnitTestCase {
public $datastore;
public $container;
public $subject;
public $legacy_storage_array;
public function setUp(): void {
$ioc = new PimpleContainer();
$ioc['container_repository'] = function( $ioc ) {
return new ContainerRepository();
};
$ioc['key_toolset'] = function( $ioc ) {
return new Key_Toolset();
};
$ioc['wp_toolset'] = function( $ioc ) {
return new WP_Toolset();
};
$ioc['container_condition_factory'] = function( $ioc ) {
return new ConditionFactory( $ioc['container_conditions'] );
};
$ioc['container_condition_translator_array'] = function( $ioc ) {
return new \Carbon_Fields\Container\Fulfillable\Translator\Array_Translator( $ioc['container_condition_factory'] );
};
$ioc['container_condition_translator_json'] = function( $ioc ) {
return new \Carbon_Fields\Container\Fulfillable\Translator\Json_Translator( $ioc['container_condition_factory'] );
};
$ioc['container_condition_fulfillable_collection'] = $ioc->factory( function( $ioc ) {
return M::mock( 'Carbon_Fields\\Container\\Fulfillable\\Fulfillable_Collection' )->shouldIgnoreMissing();
} );
$ioc['container_conditions'] = function() {
return new PimpleContainer();
};
\Carbon_Fields\Carbon_Fields::instance()->install( $ioc );
$this->datastore = M::mock( 'Carbon_Fields\\Datastore\\Key_Value_Datastore' )->makePartial();
$this->container = M::mock( 'Carbon_Fields\\Container\\Container', array( 'container_id', 'container_title', 'container_type', $ioc['container_condition_fulfillable_collection'], $ioc['container_condition_translator_json'] ) )->makePartial();
$this->container->set_datastore( $this->datastore );
$this->container->add_fields( array(
Field::make( 'text', 'crb_legacy_text' ),
Field::make( 'association', 'crb_legacy_association', 'Legacy Association' ),
Field::make( 'set', 'crb_legacy_set', 'Legacy Set' )
->add_options( array( 'one'=>'One', 'two'=>'Two', 'three'=>'Three' ) ),
Field::make( 'map', 'crb_legacy_map', 'Legacy Map' ),
Field::make( 'complex', 'crb_home_sections', __( 'Sections', 'crb' ) )
->add_fields( 'features', __('Features', 'crb'), array(
Field::make( 'complex', 'columns', __( 'Columns', 'crb' ) )
->add_fields('col1of4', __('Column 1 of 4', 'crb'), $this->crb_get_column_fields())
->add_fields('col3of4', __('Column 3 of 4', 'crb'), array(
Field::make('complex', 'rows', __('Rows', 'crb'))
->add_fields('row', __('Row', 'crb'), array(
Field::make('complex', 'cols', __('Columns', 'crb'))
->add_fields('col1of3', __('Column 1 of 3', 'crb'), array(
Field::make('map', 'map', __('Map', 'crb')),
Field::make('set', 'set', __('Set', 'crb'))
->add_options( array( 'one'=>'One', 'two'=>'Two', 'three'=>'Three' ) ),
Field::make('association', 'association', __('Association', 'crb')),
Field::make('file', 'image', __('Image', 'crb')),
Field::make('text', 'link', __('Link', 'crb')),
))
->add_fields('col2of3', __('Column 2 of 3', 'crb'), $this->crb_get_column_fields())
))
))
) ),
) );
$ioc['container_repository']->register_container( $this->container );
$this->legacy_storage_array = array(
'_crb_legacy_text' => 'lorem ipsum',
'_crb_legacy_map' => '19.0759837,72.87765590000004',
'_crb_legacy_map-address' => 'Mumbai',
'_crb_legacy_map-zoom' => '6',
'_crb_legacy_map-lng' => '72.87765590000004',
'_crb_legacy_map-lat' => '19.0759837',
'_crb_legacy_set' => 'a:1:{i:0;s:3:"one";}',
'_crb_legacy_association' => 'a:1:{i:0;s:12:"post:post:47";}',
'_crb_home_sections_features-_columns_0_col3of4-_rows_0_row-_cols_0_col1of3-_map_0-lat' => '40.7127837',
'_crb_home_sections_features-_columns_0_col3of4-_rows_0_row-_cols_0_col1of3-_map_0-lng' => '-74.0059413',
'_crb_home_sections_features-_columns_0_col3of4-_rows_0_row-_cols_0_col1of3-_map_0-zoom' => '5',
'_crb_home_sections_features-_columns_0_col3of4-_rows_0_row-_cols_0_col1of3-_map_0-address' => 'New York',
'_crb_home_sections_features-_columns_0_col3of4-_rows_0_row-_cols_0_col1of3-_map_0' => '40.7127837,-74.0059413',
'_crb_home_sections_features-_columns_0_col3of4-_rows_0_row-_cols_0_col1of3-_set_0' => 'a:2:{i:0;s:3:"one";i:1;s:5:"three";}',
'_crb_home_sections_features-_columns_0_col3of4-_rows_0_row-_cols_0_col1of3-_association_0' => 'a:1:{i:0;s:12:"post:post:47";}',
'_crb_home_sections_features-_columns_0_col3of4-_rows_0_row-_cols_0_col1of3-_image_0' => '',
'_crb_home_sections_features-_columns_0_col3of4-_rows_0_row-_cols_0_col1of3-_link_0' => 'lorem ipsum',
'_crb_home_sections_features-_columns_0_col3of4-_rows_0_row-_cols_0_col2of3-_image_1' => '65',
'_crb_home_sections_features-_columns_0_col3of4-_rows_0_row-_cols_0_col2of3-_link_1' => 'http://example.com/some-internal-path/some-file.php?some_query_arg=someval',
'_crb_home_sections_features-_columns_0_col3of4-_rows_0_row-_cols_0_col2of3-_light_1' => '',
'_crb_home_sections_features-_columns_0_col3of4-_rows_0_row-_cols_0_col2of3-_content_1' => '<h3><strong>Regular</strong> Sofas</h3>[button link="#"]More Details[/button]',
);
$this->subject = M::mock( 'Carbon_Fields\\Service\\Legacy_Storage_Service_v_1_5', array( $ioc['container_repository'], $ioc['key_toolset'] ) )->shouldDeferMissing();
}
public function tearDown(): void {
M::close();
unset( $this->subject );
}
protected function crb_get_column_fields() {
return array(
Field::make('file', 'image', __('Image', 'crb')),
Field::make('text', 'link', __('Link', 'crb'))
->set_width(50)
->set_required(true),
Field::make('checkbox', 'light', __('Lighter Section', 'crb'))
->set_width(50),
Field::make('rich_text', 'content', __('Content', 'crb')),
);
}
/**
* @covers ::get_storage_array_for_datastore
*/
public function testGetStorageArrayForDatastoreReturnsResultsForAllFields() {
$this->subject->shouldReceive( 'get_legacy_storage_array' )->andReturn( $this->legacy_storage_array );
$expected = array(
'_crb_legacy_text' => 'lorem ipsum',
'_crb_legacy_text|||0|value' => 'lorem ipsum',
'_crb_legacy_map|||0|value' => '19.0759837,72.87765590000004',
'_crb_legacy_map|||0|lat' => '19.0759837',
'_crb_legacy_map|||0|lng' => '72.87765590000004',
'_crb_legacy_map|||0|zoom' => '6',
'_crb_legacy_map|||0|address' => 'Mumbai',
'_crb_legacy_set|||0|value' => 'one',
'_crb_legacy_association|||0|value' => 'post:post:47',
'_crb_home_sections|||0|value' => 'features',
'_crb_home_sections|columns|0|0|value' => 'col3of4',
'_crb_home_sections|columns:rows|0:0|0|value' => 'row',
'_crb_home_sections|columns:rows:cols|0:0:0|0|value' => 'col1of3',
'_crb_home_sections|columns:rows:cols:map|0:0:0:0|0|value' => '40.7127837,-74.0059413',
'_crb_home_sections|columns:rows:cols:map|0:0:0:0|0|lat' => '40.7127837',
'_crb_home_sections|columns:rows:cols:map|0:0:0:0|0|lng' => '-74.0059413',
'_crb_home_sections|columns:rows:cols:map|0:0:0:0|0|zoom' => '5',
'_crb_home_sections|columns:rows:cols:map|0:0:0:0|0|address' => 'New York',
'_crb_home_sections|columns:rows:cols:set|0:0:0:0|0|value' => 'one',
'_crb_home_sections|columns:rows:cols:set|0:0:0:0|1|value' => 'three',
'_crb_home_sections|columns:rows:cols:association|0:0:0:0|0|value' => 'post:post:47',
'_crb_home_sections|columns:rows:cols:image|0:0:0:0|0|value' => '',
'_crb_home_sections|columns:rows:cols:link|0:0:0:0|0|value' => 'lorem ipsum',
'_crb_home_sections|columns:rows:cols|0:0:0|1|value' => 'col2of3',
'_crb_home_sections|columns:rows:cols:image|0:0:0:1|0|value' => '65',
'_crb_home_sections|columns:rows:cols:link|0:0:0:1|0|value' => 'http://example.com/some-internal-path/some-file.php?some_query_arg=someval',
'_crb_home_sections|columns:rows:cols:light|0:0:0:1|0|value' => '',
'_crb_home_sections|columns:rows:cols:content|0:0:0:1|0|value' => '<h3><strong>Regular</strong> Sofas</h3>[button link="#"]More Details[/button]',
);
$received = $this->subject->get_storage_array_for_datastore( $this->datastore );
$this->assertSame( $expected, $received );
}
/**
* @covers ::get_storage_array
*/
public function testGetStorageArrayReturnsSingleFieldValue() {
$this->subject->shouldReceive( 'get_legacy_storage_array' )->andReturn( array(
'_crb_legacy_text' => 'lorem ipsum',
// added junk which should be discarded
'_crb_legacy_junk_key' => 'lorem ipsum',
'_crb_legacy_junk_key-_child_0' => 'lorem ipsum',
) );
$expected = array(
(object) array(
'key' => '_crb_legacy_text',
'value' => 'lorem ipsum',
),
(object) array(
'key' => '_crb_legacy_text|||0|value',
'value' => 'lorem ipsum',
),
);
$container_fields = $this->container->get_fields();
$legacy_text_field = $container_fields[0];
$patterns = \Carbon_Fields\Carbon_Fields::resolve( 'key_toolset' )->get_storage_key_getter_patterns(
$legacy_text_field->is_simple_root_field(),
array_merge( $legacy_text_field->get_hierarchy(), array( $legacy_text_field->get_base_name() ) )
);
$received = $this->subject->get_storage_array( $this->datastore, $patterns );
$this->assertEquals( $expected, $received );
}
}

View file

@ -0,0 +1,390 @@
<?php
use Mockery as M;
use Carbon_Fields\Value_Set\Value_Set;
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
/**
* @coversDefaultClass Carbon_Fields\Value_Set\Value_Set
*/
class ValueSetTest extends WP_UnitTestCase {
public function setUp(): void {
}
public function tearDown(): void {
M::close();
}
/**
* @covers ::__construct
* @covers ::get_type
*/
public function testGetTypeReturnsCorrectType() {
$expected = Value_Set::TYPE_MULTIPLE_VALUES;
$subject = new Value_Set( $expected );
$this->assertSame( $expected, $subject->get_type() );
}
/**
* @covers ::__construct
*
* @expectedException Carbon_Fields\Exception\Incorrect_Syntax_Exception
*/
public function testInvalidTypeRaisesException() {
$subject = new Value_Set( 'invalid type' );
}
/**
* @covers ::keepalive
*/
public function testKeepaliveIsFalseForSingleValueTypes() {
$subject = new Value_Set( Value_Set::TYPE_SINGLE_VALUE );
$this->assertSame( false, $subject->keepalive() );
}
/**
* @covers ::keepalive
*/
public function testKeepaliveIsTrueForMultiValueTypes() {
$subject = new Value_Set( Value_Set::TYPE_MULTIPLE_VALUES );
$this->assertSame( true, $subject->keepalive() );
$subject = new Value_Set( Value_Set::TYPE_MULTIPLE_PROPERTIES );
$this->assertSame( true, $subject->keepalive() );
$subject = new Value_Set( Value_Set::TYPE_VALUE_SET );
$this->assertSame( true, $subject->keepalive() );
}
/**
* @covers ::is_empty
*/
public function testIsEmptyReturnsTrueForFreshInstances() {
$subject = new Value_Set();
$this->assertSame( true, $subject->is_empty() );
}
/**
* @covers ::is_empty
* @covers ::set
*/
public function testIsEmptyReturnsTrueForNull() {
$subject = new Value_Set();
$subject->set( null );
$this->assertSame( true, $subject->is_empty() );
}
/**
* @covers ::is_empty
* @covers ::set
*/
public function testIsEmptyReturnsTrueForEmptyArray() {
$subject = new Value_Set();
$subject->set( array() );
$this->assertSame( true, $subject->is_empty() );
}
/**
* @covers ::is_empty
* @covers ::set
*/
public function testIsEmptyReturnsFalseForEmptyString() {
$subject = new Value_Set();
$subject->set( '' );
$this->assertSame( false, $subject->is_empty() );
}
/**
* @covers ::is_empty
* @covers ::set
*/
public function testIsEmptyReturnsFalseForPopulatedArray() {
$subject = new Value_Set();
$subject->set( array(
Value_Set::VALUE_PROPERTY => 'test',
) );
$this->assertSame( false, $subject->is_empty() );
}
/**
* @covers ::set
* @covers ::get
*/
public function testGetReturnsNullForFreshInstances() {
$subject = new Value_Set();
$expected = null;
$this->assertSame( $expected, $subject->get() );
}
/**
* @covers ::set
* @covers ::get
*/
public function testGetReturnsNullWhenValueIsSetToNull() {
$subject = new Value_Set();
$expected = null;
$subject->set( $expected );
$this->assertSame( $expected, $subject->get() );
}
/**
* @covers ::set
* @covers ::get
*/
public function testGetReturnsStringForSingleValueType() {
$subject = new Value_Set();
$value = 'expected value';
$expected = $value;
$subject->set( array(
array(
Value_Set::VALUE_PROPERTY => $value,
),
) );
$this->assertSame( $expected, $subject->get() );
}
/**
* @covers ::set
* @covers ::get
*/
public function testGetReturnsFlatArrayForMultipleValuesType() {
$subject = new Value_Set( Value_Set::TYPE_MULTIPLE_VALUES );
$value = 'expected value';
$expected = array(
$value,
);
$subject->set( array(
array(
Value_Set::VALUE_PROPERTY => $value,
),
) );
$this->assertSame( $expected, $subject->get() );
}
/**
* @covers ::set
* @covers ::get
*/
public function testGetReturnsAssociativeArrayForMultiplePropertiesType() {
$subject = new Value_Set( Value_Set::TYPE_MULTIPLE_PROPERTIES );
$value = 'expected value';
$expected = array(
Value_Set::VALUE_PROPERTY => $value,
);
$subject->set( array(
array(
Value_Set::VALUE_PROPERTY => $value,
),
) );
$this->assertSame( $expected, $subject->get() );
}
/**
* @covers ::set
* @covers ::get
*/
public function testGetReturnsArrayOfAssociativeArraysForValueSetType() {
$subject = new Value_Set( Value_Set::TYPE_VALUE_SET );
$value = 'expected value';
$expected = array(
array(
Value_Set::VALUE_PROPERTY => $value,
),
);
$subject->set( array(
array(
Value_Set::VALUE_PROPERTY => $value,
),
) );
$this->assertSame( $expected, $subject->get() );
}
/**
* @covers ::set
* @covers ::get_set
*/
public function testGetReturnsRawValueSetForSingleValueType() {
$subject = new Value_Set();
$value = 'expected value';
$expected = array(
array(
Value_Set::VALUE_PROPERTY => $value,
),
);
$subject->set( array(
array(
Value_Set::VALUE_PROPERTY => $value,
),
) );
$this->assertSame( $expected, $subject->get_set() );
}
/**
* @covers ::set
* @covers ::get
*/
public function testGetReturnsValueSetWithMissingPropertiesAddedIn() {
$subject = new Value_Set( Value_Set::TYPE_VALUE_SET, array( 'foo' => '', 'bar' => '' ) );
$value = '';
$expected = array(
array(
Value_Set::VALUE_PROPERTY => $value,
'foo' => '',
'bar' => '',
),
);
$subject->set( array(
array(
Value_Set::VALUE_PROPERTY => $value,
),
) );
$this->assertSame( $expected, $subject->get_set() );
}
/**
* @covers ::set
* @covers ::get
*/
public function testGetReturnsValueSetWithMissingPropertiesAddedInWithDefaultValues() {
$subject = new Value_Set( Value_Set::TYPE_VALUE_SET, array( 'foo' => 'bar', 'bar' => 'foo' ) );
$value = '';
$expected = array(
array(
Value_Set::VALUE_PROPERTY => $value,
'foo' => 'bar',
'bar' => 'foo',
),
);
$subject->set( array(
array(
Value_Set::VALUE_PROPERTY => $value,
),
) );
$this->assertSame( $expected, $subject->get_set() );
}
/**
* @covers ::set
* @covers ::get
*/
public function testGetReturnsValueSetWithOnlyMissingPropertiesAddedInWithDefaultValues() {
$subject = new Value_Set( Value_Set::TYPE_VALUE_SET, array( 'foo' => 'bar', 'bar' => 'foo' ) );
$value = '';
$expected = array(
array(
Value_Set::VALUE_PROPERTY => $value,
'foo' => '',
'bar' => 'foo',
),
array(
Value_Set::VALUE_PROPERTY => $value,
'foo' => 'bar',
'bar' => '',
),
);
$subject->set( array(
array(
Value_Set::VALUE_PROPERTY => $value,
'foo' => '',
),
array(
Value_Set::VALUE_PROPERTY => $value,
'bar' => '',
),
) );
$this->assertSame( $expected, $subject->get_set() );
}
/**
* @covers ::set
* @covers ::get
*/
public function testGetSetReturnsFullSetWhenSetIsPassedAString() {
$subject = new Value_Set( Value_Set::TYPE_VALUE_SET, array( 'foo' => '', 'bar' => '' ) );
$value = 'expected value';
$expected = array(
array(
Value_Set::VALUE_PROPERTY => $value,
'foo' => '',
'bar' => '',
),
);
$subject->set( $value );
$this->assertSame( $expected, $subject->get_set() );
}
/**
* @covers ::set
* @covers ::get
*/
public function testGetSetReturnsFullSetWhenSetIsPassedAFlatArray() {
$subject = new Value_Set( Value_Set::TYPE_VALUE_SET, array( 'foo' => '', 'bar' => '' ) );
$value1 = 'value1';
$value2 = 'value2';
$expected = array(
array(
Value_Set::VALUE_PROPERTY => $value1,
'foo' => '',
'bar' => '',
),
array(
Value_Set::VALUE_PROPERTY => $value2,
'foo' => '',
'bar' => '',
),
);
$subject->set( array(
$value1,
$value2,
) );
$this->assertSame( $expected, $subject->get_set() );
}
/**
* @covers ::set
* @covers ::get
*/
public function testGetSetReturnsFullSetWhenSetIsPassedAnAssociativeArray() {
$subject = new Value_Set( Value_Set::TYPE_VALUE_SET, array( 'foo' => '', 'bar' => '' ) );
$value = 'expected value';
$expected = array(
array(
Value_Set::VALUE_PROPERTY => $value,
'foo' => 'bar',
'bar' => 'foo',
),
);
$subject->set( array(
Value_Set::VALUE_PROPERTY => $value,
'foo' => 'bar',
'bar' => 'foo',
) );
$this->assertSame( $expected, $subject->get_set() );
}
/**
* @covers ::set
* @covers ::get
*/
public function testGetSetReturnsFullSetWhenSetIsPassedARawValueSet() {
$subject = new Value_Set( Value_Set::TYPE_VALUE_SET, array( 'foo' => '', 'bar' => '' ) );
$value1 = 'value1';
$value2 = 'value2';
$expected = array(
array(
Value_Set::VALUE_PROPERTY => $value1,
'foo' => 'bar',
'bar' => 'foo',
),
array(
Value_Set::VALUE_PROPERTY => $value2,
'foo' => 'bar',
'bar' => 'foo',
),
);
$subject->set( $expected );
$this->assertSame( $expected, $subject->get_set() );
}
}