wordpress-develop/tests/phpunit/tests/bookmark/getBookmark.php
Sergey Biryukov ddb409edca Build/Test Tools: Implement use of the void solution.
> PHPUnit 8.0.0 introduced a `void` return type declaration to the "fixture" methods – `setUpBeforeClass()`, `setUp()`, `tearDown()` and `tearDownAfterClass()`. As the `void` return type was not introduced until PHP 7.1, this makes it more difficult to create cross-version compatible tests when using fixtures, due to signature mismatches.
>
> The `Yoast\PHPUnitPolyfills\TestCases\TestCase` overcomes the signature mismatch by having two versions. The correct one will be loaded depending on the PHPUnit version being used.
>
> When using this TestCase, if an individual test, or another TestCase which extends this TestCase, needs to overload any of the "fixture" methods, it should do so by using a snake_case variant of the original fixture method name, i.e. `set_up_before_class()`, `set_up()`, `assert_pre_conditions()`, `assert_post_conditions()`, `tear_down()`, and `tear_down_after_class()`.
>
> The snake_case methods will automatically be called by PHPUnit.
>
> > IMPORTANT: The snake_case methods should not call the PHPUnit parent, i.e. do not use `parent::setUp()` from within an overloaded `set_up()` method. If necessary, DO call `parent::set_up()`.

Reference: https://github.com/Yoast/PHPUnit-Polyfills#testcases

This commit renames all declared fixture methods, and calls to parent versions of those fixture methods, from camelCase to snake_case.

Follow-up to [51559-51567].

Props jrf, hellofromTonya, johnbillion, netweb, dd32, pputzer, SergeyBiryukov.
See #46149.

git-svn-id: https://develop.svn.wordpress.org/trunk@51568 602fd350-edb4-49c9-b593-d223f7449a82
2021-08-07 10:29:41 +00:00

413 lines
11 KiB
PHP

<?php
/**
* @group bookmark
* @covers ::get_bookmark
*/
class Tests_Bookmark_GetBookmark extends WP_UnitTestCase {
/**
* Instance of the bookmark object.
*
* @var stdClass
*/
private static $bookmark;
/**
* Create and get a bookmark for the tests.
*
* @param WP_UnitTest_Factory $factory
*/
public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
self::$bookmark = $factory->bookmark->create_and_get();
// Delete the bookmark that was cached when the factory invoked get_bookmark().
wp_cache_delete( self::$bookmark->link_id, 'bookmark' );
}
/**
* Delete the bookmark before existing the test class.
*/
public static function wpTearDownAfterClass() {
wp_delete_link( self::$bookmark->link_id );
}
/**
* Reset globals after each test.
*/
public function tear_down() {
unset( $GLOBALS['link'] );
parent::tear_down();
}
/**
* Path 1A: Given empty bookmark and global link exists.
*
* @dataProvider data_when_empty_bookmark
*/
public function test_should_return_global_link_in_requested_output_format( $args ) {
$GLOBALS['link'] = self::$bookmark;
$args = $this->init_func_args( $args, 0 );
$actual_bookmark = get_bookmark( ...$args );
$expected = $this->maybe_format_expected_data( $args, $GLOBALS['link'] );
$this->assertArrayHasKey( 'link', $GLOBALS );
$this->assertSame( $expected, $actual_bookmark );
// Should bypass the cache.
$this->assertFalse( wp_cache_get( self::$bookmark->link_id, 'bookmark' ) );
}
/**
* Path 1B: Given empty bookmark and global link does not exist.
*
* @dataProvider data_when_empty_bookmark
*/
public function test_should_return_null( $args ) {
$args = $this->init_func_args( $args, 0 );
// Run the function and test results.
$actual_bookmark = get_bookmark( ...$args );
$this->assertArrayNotHasKey( 'link', $GLOBALS );
$this->assertNull( $actual_bookmark );
$this->assertFalse( wp_cache_get( self::$bookmark->link_id, 'bookmark' ) );
}
/**
* Path 1 data provider, i.e. when given empty bookmark.
*/
public function data_when_empty_bookmark() {
return array(
// Unhappy path.
'with bookmark type mismatch' => array(
array(
'bookmark' => '',
),
),
'with invalid output' => array(
array(
'bookmark' => 0,
'output' => 'invalid',
),
),
'with bookmark type mismatch and invalid output' => array(
array(
'bookmark' => null,
'output' => 'invalid',
),
),
// Happy path.
'with defaults' => array(
array(
'bookmark' => 0,
),
),
'with non-default output' => array(
array(
'bookmark' => 0,
'output' => ARRAY_A,
),
),
'with non-default filter' => array(
array(
'bookmark' => 0,
'filter' => 'display',
),
),
'with non-default output and filter' => array(
array(
'bookmark' => 0,
'output' => ARRAY_N,
'filter' => 'display',
),
),
);
}
/**
* Path 2: Bookmark instance is given.
*
* @dataProvider data_when_instance_bookmark
*/
public function test_should_cache_bookmark_when_given_instance( $args ) {
$args = $this->init_func_args( $args );
$bookmark = $args[0];
$expected = $this->maybe_format_expected_data( $args, $bookmark );
// Check the cache does not exist before the test.
$this->assertFalse( wp_cache_get( $bookmark->link_id, 'bookmark' ) );
// Run the function and test results.
$actual_bookmark = get_bookmark( ...$args );
$this->assertSame( $expected, $actual_bookmark );
// Check the bookmark was cached.
$actual_cache = wp_cache_get( $bookmark->link_id, 'bookmark' );
$this->assertEquals( $bookmark, $actual_cache );
}
/**
* Path 2 data provider, i.e. when bookmark instance is given.
*/
public function data_when_instance_bookmark() {
return array(
// Unhappy path.
'with incomplete bookmark data' => array(
array(
'bookmark' => (object) array(
'link_id' => '100',
),
),
),
'with invalid output' => array(
array(
'output' => 'invalid',
),
),
'with invalid filter' => array(
array(
'filter' => 'invalid',
),
),
// Happy path.
'with defaults' => array(
array(),
),
'with non-default output' => array(
array(
'output' => ARRAY_A,
),
),
'with non-default filter' => array(
array(
'filter' => 'display',
),
),
'with non-default output and filter' => array(
array(
'output' => ARRAY_N,
'filter' => 'display',
),
),
);
}
/**
* Path 3A: Uses the global link when exists and the given bookmark link ID matches the global link.
*
* @dataProvider data_when_else
*
* @param array $args Function argument list.
*/
public function test_should_return_global_when_else( $args ) {
$args = $this->init_func_args( $args, self::$bookmark->link_id );
$GLOBALS['link'] = self::$bookmark;
$expected = $this->maybe_format_expected_data( $args, $GLOBALS['link'] );
// Run the function and test results.
$actual_bookmark = get_bookmark( ...$args );
$this->assertSame( $expected, $actual_bookmark );
$this->assertFalse( wp_cache_get( self::$bookmark->link_id, 'bookmark' ) );
}
/**
* Path 3B: Pulls from cache when given existing bookmark link ID.
*
* @dataProvider data_when_else
*
* @param array $args Function argument list.
*/
public function test_should_return_cached_bookmark_when_given_existing_link_id( $args ) {
// Cache the bookmark instance to setup the test.
wp_cache_add( self::$bookmark->link_id, self::$bookmark, 'bookmark' );
$args = $this->init_func_args( $args, self::$bookmark->link_id );
$expected = $this->maybe_format_expected_data( $args, self::$bookmark );
// Run the function and test results.
$actual_bookmark = get_bookmark( ...$args );
/*
* For non-array output type, use assertEquals(). Why? The object pulled from the cache
* will have the same property values but will be a different object than the expected object.
*/
if ( is_object( $expected ) ) {
$this->assertEquals( $expected, $actual_bookmark );
} else {
$this->assertSameSets( $expected, $actual_bookmark );
}
// Check the bookmark was cached.
$actual_cache = wp_cache_get( self::$bookmark->link_id, 'bookmark' );
$this->assertEquals( self::$bookmark, $actual_cache );
}
/**
* Path 3C: Attempts to pull non-existent bookmark from database.
*
* @dataProvider data_when_else
*
* @param array $args Function argument list.
*/
public function test_should_return_null_when_bookmark_not_in_database( $args ) {
$bookmark_link_id = self::$bookmark->link_id * 100;
$args = $this->init_func_args( $args, $bookmark_link_id );
// Validate it will run path 6.
$this->assertFalse( wp_cache_get( $bookmark_link_id, 'bookmark' ) );
$this->assertArrayNotHasKey( 'link', $GLOBALS );
global $wpdb;
$db_actual = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->links WHERE link_id = %d LIMIT 1", $bookmark_link_id ) );
$this->assertNull( $db_actual );
// Run the function and test results.
$actual_bookmark = get_bookmark( ...$args );
$this->assertNull( $actual_bookmark );
$this->assertFalse( wp_cache_get( $bookmark_link_id, 'bookmark' ) );
}
/**
* Path 3D: Pulls existing bookmark from the database.
*
* @dataProvider data_when_else
*
* @param array $args Function argument list.
*/
public function test_should_return_existing_bookmark_from_database( $args ) {
$args = $this->init_func_args( $args, self::$bookmark->link_id );
$expected = $this->maybe_format_expected_data( $args, self::$bookmark );
// Validate it will run path 5.
$this->assertFalse( wp_cache_get( self::$bookmark->link_id, 'bookmark' ) );
$this->assertArrayNotHasKey( 'link', $GLOBALS );
// Run the function and test results.
$actual_bookmark = get_bookmark( ...$args );
/*
* For non-array output type, use assertEquals(). Why? The object pulled from the database
* will have the same property values but will be a different object than the expected object.
*/
if ( is_object( $expected ) ) {
$this->assertEquals( $expected, $actual_bookmark );
} else {
$this->assertSameSets( $expected, $actual_bookmark );
}
// Check the bookmark was cached.
$actual_cache = wp_cache_get( self::$bookmark->link_id, 'bookmark' );
$this->assertEquals( self::$bookmark, $actual_cache );
}
/**
* Path 3's data provider which covers the "else" branch, i.e. when the bookmark argument is not empty and
* not an object.
*/
public function data_when_else() {
return array(
// Unhappy path.
'with invalid output' => array(
array(
'output' => 'invalid',
),
),
'with invalid filter' => array(
array(
'filter' => 'invalid',
),
),
// Happy path.
'with defaults' => array(
array(),
),
'with non-default output' => array(
array(
'output' => ARRAY_A,
),
),
'with non-default filter' => array(
array(
'filter' => 'display',
),
),
'with non-default output and filter' => array(
array(
'output' => ARRAY_N,
'filter' => 'display',
),
),
);
}
/**
* @ticket 53235
*/
public function test_numeric_properties_should_be_cast_to_ints() {
$contexts = array( 'raw', 'edit', 'db', 'display', 'attribute', 'js' );
foreach ( $contexts as $context ) {
$bookmark = get_bookmark( self::$bookmark->link_id, OBJECT, $context );
$this->assertIsInt( $bookmark->link_id );
$this->assertIsInt( $bookmark->link_rating );
}
}
/**
* Initialize the get_bookmark's function arguments to match the order of the function's signature and
* reduce code in the tests.
*
* @param array $args Function argument list.
* @param int|stdClass $bookmark Optional. Bookmark's cache key or instance.
* @return array Ordered argument list.
*/
private function init_func_args( array $args, $bookmark = null ) {
// The defaults sets the order to match the function's arguments as well as setting the default values.
$defaults = array(
'bookmark' => self::$bookmark,
'output' => OBJECT,
'filter' => 'raw',
);
$args = array_merge( $defaults, $args );
// When given a bookmark, use it.
if ( ! is_null( $bookmark ) ) {
$args['bookmark'] = $bookmark;
}
/*
* Strip out the keys. Why? The splat operator (...) does not work with associative arrays,
* except for in PHP 8 where the keys are named arguments.
*/
return array_values( $args );
}
/**
* Maybe format the bookmark's expected data.
*
* @param array $args Function argument list.
* @param int|stdClass|null $bookmark Optional. Bookmark's cache key or instance.
* @return array|stdClass bookmark's data.
*/
private function maybe_format_expected_data( array $args, $bookmark = null ) {
if ( is_null( $bookmark ) ) {
$bookmark = self::$bookmark;
}
switch ( $args[1] ) {
case ARRAY_A:
case ARRAY_N:
$expected = get_object_vars( $bookmark );
if ( ARRAY_N === $args[1] ) {
$expected = array_values( $expected );
}
return $expected;
default:
return $bookmark;
}
}
}