Skip to content
Closed
Changes from 19 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
102d602
Adds empty bookmark tests.
Apr 7, 2021
a93df37
Adds tests when given bookmark instance.
Apr 7, 2021
dab9e40
Refactored to reduce params init and formatting expected data.
Apr 7, 2021
ae4c802
Speed up the test setup/teardown.
Apr 8, 2021
19a6c5e
Split out the data provider for the groups of tests.
Apr 8, 2021
58013e7
Improves the init_func_params for overriding the bookmark.
Apr 8, 2021
080cc85
Change param to arg to better match PHP docs.
Apr 8, 2021
bb83aee
Adds unhappy path to empty bookmark tests.
Apr 8, 2021
1d3f012
Adds unhappy path test cases to bookmark instance tests.
Apr 8, 2021
f97b83a
Adds @covers.
Apr 8, 2021
90b7062
Adds else path when global link is set and its link_id matches given …
Apr 8, 2021
3d2851d
Adds Path 4 - test pulling from cache when existing link ID given.
Apr 8, 2021
e365e5d
Adds Path 5 tests - pulls existing record from db.
Apr 8, 2021
fd71f83
Adds Path 6 - requested link ID does not exist in db.
Apr 8, 2021
0710645
Improves documentation and consistency.
Apr 8, 2021
9a50500
Rearranges the else branch tests to follow logic flow.
Apr 8, 2021
87caec6
Combines path 2 tests for consistency.
Apr 8, 2021
a4a6ded
Create bookmark in setUp to avoid downstream conflicts.
Apr 8, 2021
c50aeb9
Removes is numeric assertion.
Apr 8, 2021
3111683
Removes deleting bookmark from cache during tearDown.
Apr 23, 2021
6b340f0
Fixes multiline comments and removes empty line in DocBlock.
Apr 23, 2021
829df40
Create and delete bookmark using wp static methods.
Apr 23, 2021
263f7cc
Use custom WP assertSameSets.
Apr 23, 2021
9fcb19b
Removes changes to package-lock.json from PR.
Apr 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
384 changes: 384 additions & 0 deletions tests/phpunit/tests/bookmark/getBookmark.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,384 @@
<?php

/**
* @group bookmark
* @covers ::get_bookmark
*/
class Tests_Bookmark_GetBookmark extends WP_UnitTestCase {
/**
* Instance of the bookmark object.
*
* @var stdClass
*/
private $bookmark;

public function setUp() {
parent::setUp();

$this->bookmark = self::factory()->bookmark->create_and_get();
wp_cache_delete( $this->bookmark->link_id, 'bookmark' );
}

public function tearDown() {
unset( $GLOBALS['link'] );
if ( isset( $this->bookmark->link_id ) ) {
wp_cache_delete( $this->bookmark->link_id, 'bookmark' );
}

parent::tearDown();
}

/**
* 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'] = $this->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( $this->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( $this->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, $this->bookmark->link_id );
$GLOBALS['link'] = $this->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( $this->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( $this->bookmark->link_id, $this->bookmark, 'bookmark' );
$args = $this->init_func_args( $args, $this->bookmark->link_id );
$expected = $this->maybe_format_expected_data( $args, $this->bookmark );

// Run the function and test results.
$actual_bookmark = get_bookmark( ...$args );

// For non-array output type, use assetEquals. Why? The object pulled from 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->assertSame( $expected, $actual_bookmark );
}

// Check the bookmark was cached.
$actual_cache = wp_cache_get( $this->bookmark->link_id, 'bookmark' );
$this->assertEquals( $this->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 = $this->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, $this->bookmark->link_id );
$expected = $this->maybe_format_expected_data( $args, $this->bookmark );

// Validate it will run path 5.
$this->assertFalse( wp_cache_get( $this->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 assetEquals. 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->assertSame( $expected, $actual_bookmark );
}

// Check the bookmark was cached.
$actual_cache = wp_cache_get( $this->bookmark->link_id, 'bookmark' );
$this->assertEquals( $this->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',
),
),
);
}

/**
* 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' => $this->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 = $this->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;
}
}
}