Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,8 @@
<rule ref="WordPress.Files">
<exclude-pattern>tests/*</exclude-pattern>
</rule>

<rule ref="Squiz.PHP.DisallowMultipleAssignments.Found">
<exclude-pattern>tests/*</exclude-pattern>
</rule>
</ruleset>
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ All notable changes to `WP Curate` will be documented in this file.
## Unreleased

- Upgrade to PHPStan to 2.0.
- Added unit tests for existing plugin functionality.

## 2.7.2 - 2025-10-15

Expand Down
72 changes: 72 additions & 0 deletions tests/Feature/BlockTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php
/**
* WP Curate Tests: Block Test
*
* @package wp-curate
*/

namespace Alley\WP\WP_Curate\Tests\Feature;

use Alley\WP\WP_Curate\Tests\TestCase;

use function Mantle\Testing\block_factory;

/**
* Test the general block functionality of WP Curate.
*/
class BlockTest extends TestCase {
/**
* Test that a homepage curated with the query block works as expected.
*/
public function test_curate_a_homepage(): void {
$posts = static::create_ordered_set( 10 )->reverse()->values();

$this->set_front_page( $page = static::factory()->page->create_and_get( [
'post_content' => block_factory()->preset( 'wp-curate/query', [
'attributes' => [
'numberOfPosts' => 8,
],
] ),
] ) );

$this->get( '/' )
->assertOk()
->assertQueryTrue( 'is_front_page', 'is_page', 'is_singular' )
->assertQueriedObjectId( $page->ID )
// Ensure all posts appear in the proper order.
->assertSeeInOrder( $posts->slice( 0, 8 )->pluck( 'post_title' )->all() )
// Ensure posts 9 and 10 do not appear (only 8 should appear).
->assertDontSee( $posts->get( 8 )->post_title )
->assertDontSee( $posts->get( 9 )->post_title )
// Ensure excerpts are shown.
->assertQuerySelectorExists( '.wp-block-post-excerpt__excerpt' );
}

/**
* Test that a page curated with the query block with an offset works as expected.
*/
public function test_curate_a_page_with_offset(): void {
$posts = static::create_ordered_set( 10 )->reverse()->values();

$this->set_front_page( $page = static::factory()->page->create_and_get( [
'post_content' => block_factory()->preset( 'wp-curate/query', [
'attributes' => [
'offset' => 2,
'numberOfPosts' => 8,
],
] ),
] ) );

$this->get( '/' )
->assertOk()
->assertQueryTrue( 'is_front_page', 'is_page', 'is_singular' )
->assertQueriedObjectId( $page->ID )
// Ensure all posts appear in the proper order.
->assertSeeInOrder( $posts->slice( 2, 10 )->pluck( 'post_title' )->all() )
// Ensure posts 1 and 2 do not appear (they are offset).
->assertDontSee( $posts->get( 0 )->post_title )
->assertDontSee( $posts->get( 1 )->post_title )
// Ensure excerpts are shown.
->assertQuerySelectorExists( '.wp-block-post-excerpt__excerpt' );
}
}
81 changes: 81 additions & 0 deletions tests/Feature/DeduplicationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php
/**
* WP Curate Tests: Deduplication Test
*
* @package wp-curate
*/

namespace Alley\WP\WP_Curate\Tests\Feature;

use Alley\WP\WP_Curate\Tests\TestCase;

use function Mantle\Testing\block_factory;

/**
* Test the deduplication functionality of the plugin.
*/
class DeduplicationTest extends TestCase {
/**
* Test that deduplication works across two query blocks on the same page.
*/
public function test_it_can_deduplicate_across_two_query_blocks(): void {
$posts = static::create_ordered_set( 10 )->reverse()->values();

$this->set_front_page( $page = static::factory()->page->with_meta( 'wp_curate_deduplication', '1' )->create_and_get( [
'post_content' => block_factory()->blocks(
block_factory()->preset( 'wp-curate/query', [
'attributes' => [
'numberOfPosts' => 5,
],
] ),
block_factory()->preset( 'wp-curate/query', [
'attributes' => [
'numberOfPosts' => 5,
],
] ),
),
] ) );

$this->get( '/' )
->assertOk()
->assertQueryTrue( 'is_front_page', 'is_page', 'is_singular' )
->assertQueriedObjectId( $page->ID )
// Ensure all posts appear in the proper order without duplicates.
->assertSeeInOrder( $posts->pluck( 'post_title' )->all() );
}

/**
* Test that a individual query block can disable deduplication on a per-block basis.
*/
public function test_it_can_override_deduplication_per_block(): void {
$posts = static::create_ordered_set( 10 )->reverse()->values();

$this->set_front_page( $page = static::factory()->page->with_meta( 'wp_curate_deduplication', '1' )->create_and_get( [
'post_content' => block_factory()->blocks(
block_factory()->preset( 'wp-curate/query', [
'attributes' => [
'numberOfPosts' => 5,
],
] ),
block_factory()->preset( 'wp-curate/query', [
'attributes' => [
'deduplication' => 'never',
'numberOfPosts' => 5,
],
] ),
),
] ) );

$this->get( '/' )
->assertOk()
->assertQueryTrue( 'is_front_page', 'is_page', 'is_singular' )
->assertQueriedObjectId( $page->ID )
// Ensure all posts appear in the proper order without duplicates.
->assertSeeInOrder( [
...$posts->slice( 0, 5 )->pluck( 'post_title' )->all(),
...$posts->slice( 0, 5 )->pluck( 'post_title' )->all(),
] )
// Ensure posts 6 through 10 do not appear (only first 5 should appear).
->assertDontSee( $posts->get( 5 )->post_title );
}
}
143 changes: 143 additions & 0 deletions tests/Feature/PinnedPostTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php
/**
* WP Curate Tests: Pinned Post Test
*
* @package wp-curate
*/

namespace Alley\WP\WP_Curate\Tests\Feature;

use Alley\WP\WP_Curate\Tests\TestCase;

use function Mantle\Support\Helpers\collect;
use function Mantle\Testing\block_factory;

/**
* Test the pinned post functionality of the plugin.
*/
class PinnedPostTest extends TestCase {
/**
* Test that pinned posts appear at the top of a query.
*/
public function test_it_can_pin_a_post_at_the_top_of_a_query(): void {
$posts = static::create_ordered_set( 5 );

$pinned_posts = collect( [ $posts->pull( 2 ), $posts->pull( 4 ) ] );

$this->set_front_page( $page = static::factory()->page->create_and_get( [
'post_content' => block_factory()->preset( 'wp-curate/query', [
'attributes' => [
'numberOfPosts' => 8,
'posts' => $pinned_posts->pluck( 'ID' )->all(),
],
] ),
] ) );

$this->get( '/' )
->assertOk()
->assertQueryTrue( 'is_front_page', 'is_page', 'is_singular' )
->assertQueriedObjectId( $page->ID )
->assertSeeInOrder( [
// Ensure the pinned posts are at the top.
$pinned_posts[0]->post_title,
$pinned_posts[1]->post_title,
// Followed by the rest of the posts in reverse order.
...$posts->reverse()->values()->pluck( 'post_title' )->all(),
] );
}

/**
* Test that pinned posts can be placed at specific positions in a query.
*/
public function test_it_can_pin_at_specific_positions(): void {
$posts = static::create_ordered_set( 6 );

// Pin the posts at positions 1 and 3 (0-based).
$pinned_posts = collect( [
null,
$posts->pull( 1 )->ID,
null,
$posts->pull( 3 )->ID,
] );

$this->set_front_page( $page = static::factory()->page->create_and_get( [
'post_content' => block_factory()->preset( 'wp-curate/query', [
'attributes' => [
'numberOfPosts' => 8,
'posts' => $pinned_posts->all(),
],
] ),
] ) );

// Build the expected order of posts with pinned posts in place (#1 and #3).
$expected_order = $posts->reverse()->values();
$expected_order->splice( 1, 0, [ get_post( $pinned_posts[1] ) ] );
$expected_order->splice( 3, 0, [ get_post( $pinned_posts[3] ) ] );

$this->get( '/' )
->assertOk()
->assertQueryTrue( 'is_front_page', 'is_page', 'is_singular' )
->assertQueriedObjectId( $page->ID )
->assertSeeInOrder( $expected_order->pluck( 'post_title' )->all() );
}

/**
* Test that a scheduled post can be pinned before it is published but won't
* appear on the front end until published.
*/
public function test_it_can_pin_a_scheduled_post_but_will_not_display_it(): void {
$posts = static::create_ordered_set( 5 );

$scheduled_post = static::factory()->post->create_and_get( [
'post_title' => 'Scheduled Post',
'post_status' => 'future',
'post_date' => gmdate( 'Y-m-d H:i:s', time() + DAY_IN_SECONDS ),
] );

$this->get( $scheduled_post )->assertNotFound();

$this->set_front_page( $page = static::factory()->page->create_and_get( [
'post_content' => block_factory()->preset( 'wp-curate/query', [
'attributes' => [
'numberOfPosts' => 8,
'posts' => [ $scheduled_post->ID ],
],
] ),
] ) );

$this->get( '/' )
->assertOk()
->assertQueryTrue( 'is_front_page', 'is_page', 'is_singular' )
->assertQueriedObjectId( $page->ID )
->assertDontSeeText( $scheduled_post->post_title )
->assertSeeInOrder( $posts->reverse()->values()->pluck( 'post_title' )->all() );
}

/**
* Test that a draft post can be pinned but will not appear on the front end.
*/
public function test_it_will_not_display_a_draft_pinned_post(): void {
$posts = static::create_ordered_set( 5 );

$draft_post = static::factory()->post->create_and_get( [
'post_title' => 'Draft Post',
'post_status' => 'draft',
] );

$this->set_front_page( $page = static::factory()->page->create_and_get( [
'post_content' => block_factory()->preset( 'wp-curate/query', [
'attributes' => [
'numberOfPosts' => 8,
'posts' => [ $draft_post->ID ],
],
] ),
] ) );

$this->get( '/' )
->assertOk()
->assertQueryTrue( 'is_front_page', 'is_page', 'is_singular' )
->assertQueriedObjectId( $page->ID )
->assertDontSeeText( $draft_post->post_title )
->assertSeeInOrder( $posts->reverse()->values()->pluck( 'post_title' )->all() );
}
}
Loading