Files
old-v2-backend/wordpress/wp-content/plugins/wp-graphql/tests/wpunit/PostObjectConnectionQueriesTest.php

708 lines
19 KiB
PHP
Raw Normal View History

2018-06-25 00:00:37 +02:00
<?php
class PostObjectConnectionQueriesTest extends \Codeception\TestCase\WPTestCase {
public $current_time;
public $current_date;
public $current_date_gmt;
public $created_post_ids;
public $admin;
public function setUp() {
parent::setUp();
$this->current_time = strtotime( '- 1 day' );
$this->current_date = date( 'Y-m-d H:i:s', $this->current_time );
$this->current_date_gmt = gmdate( 'Y-m-d H:i:s', $this->current_time );
$this->admin = $this->factory()->user->create( [
'role' => 'administrator',
] );
$this->created_post_ids = $this->create_posts();
$this->app_context = new \WPGraphQL\AppContext();
$this->app_info = new \GraphQL\Type\Definition\ResolveInfo( array() );
}
public function tearDown() {
parent::tearDown();
}
public function createPostObject( $args ) {
/**
* Set up the $defaults
*/
$defaults = [
'post_author' => $this->admin,
'post_content' => 'Test page content',
'post_excerpt' => 'Test excerpt',
'post_status' => 'publish',
'post_title' => 'Test Title',
'post_type' => 'post',
'post_date' => $this->current_date,
'has_password' => false,
'post_password'=> null,
];
/**
* Combine the defaults with the $args that were
* passed through
*/
$args = array_merge( $defaults, $args );
/**
* Create the page
*/
$post_id = $this->factory->post->create( $args );
/**
* Update the _edit_last and _edit_lock fields to simulate a user editing the page to
* test retrieving the fields
*
* @since 0.0.5
*/
update_post_meta( $post_id, '_edit_lock', $this->current_time . ':' . $this->admin );
update_post_meta( $post_id, '_edit_last', $this->admin );
/**
* Return the $id of the post_object that was created
*/
return $post_id;
}
/**
* Creates several posts (with different timestamps) for use in cursor query tests
*
* @return array
*/
public function create_posts() {
// Create 20 posts
$created_posts = [];
for ( $i = 1; $i <= 200; $i ++ ) {
// Set the date 1 minute apart for each post
$date = date( 'Y-m-d H:i:s', strtotime( "-1 day +{$i} minutes" ) );
$created_posts[ $i ] = $this->createPostObject( [
'post_type' => 'post',
'post_date' => $date,
'post_status' => 'publish',
'post_title' => $i,
] );
}
return $created_posts;
}
public function postsQuery( $variables ) {
$query = 'query postsQuery($first:Int $last:Int $after:String $before:String $where:RootPostsQueryArgs){
posts( first:$first last:$last after:$after before:$before where:$where ) {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
cursor
node {
id
postId
title
date
}
}
nodes {
id
postId
}
}
}';
return do_graphql_request( $query, 'postsQuery', $variables );
}
public function testFirstPost() {
/**
* Here we're querying the first post in our dataset
*/
$variables = [
'first' => 1,
];
$results = $this->postsQuery( $variables );
/**
* Let's query the first post in our data set so we can test against it
*/
$first_post = new WP_Query( [
'posts_per_page' => 1,
] );
$first_post_id = $first_post->posts[0]->ID;
$expected_cursor = \GraphQLRelay\Connection\ArrayConnection::offsetToCursor( $first_post_id );
$this->assertNotEmpty( $results );
$this->assertEquals( 1, count( $results['data']['posts']['edges'] ) );
$this->assertEquals( $first_post_id, $results['data']['posts']['edges'][0]['node']['postId'] );
$this->assertEquals( $expected_cursor, $results['data']['posts']['edges'][0]['cursor'] );
$this->assertEquals( $expected_cursor, $results['data']['posts']['pageInfo']['startCursor'] );
$this->assertEquals( $expected_cursor, $results['data']['posts']['pageInfo']['endCursor'] );
$this->assertEquals( $first_post_id, $results['data']['posts']['nodes'][0]['postId'] );
$this->forwardPagination( $expected_cursor );
}
public function testLastPost() {
/**
* Here we're trying to query the last post in our dataset
*/
$variables = [
'last' => 1,
];
$results = $this->postsQuery( $variables );
/**
* Let's query the last post in our data set so we can test against it
*/
$last_post = new WP_Query( [
'posts_per_page' => 1,
'order' => 'ASC',
] );
$last_post_id = $last_post->posts[0]->ID;
$expected_cursor = \GraphQLRelay\Connection\ArrayConnection::offsetToCursor( $last_post_id );
$this->assertNotEmpty( $results );
$this->assertEquals( 1, count( $results['data']['posts']['edges'] ) );
$this->assertEquals( $last_post_id, $results['data']['posts']['edges'][0]['node']['postId'] );
$this->assertEquals( $expected_cursor, $results['data']['posts']['edges'][0]['cursor'] );
$this->assertEquals( $expected_cursor, $results['data']['posts']['pageInfo']['startCursor'] );
$this->assertEquals( $expected_cursor, $results['data']['posts']['pageInfo']['endCursor'] );
$this->backwardPagination( $expected_cursor );
}
public function forwardPagination( $cursor ) {
$variables = [
'first' => 1,
'after' => $cursor,
];
$results = $this->postsQuery( $variables );
$second_post = new WP_Query( [
'posts_per_page' => 1,
'paged' => 2,
] );
$second_post_id = $second_post->posts[0]->ID;
$expected_cursor = \GraphQLRelay\Connection\ArrayConnection::offsetToCursor( $second_post_id );
$this->assertNotEmpty( $results );
$this->assertEquals( 1, count( $results['data']['posts']['edges'] ) );
$this->assertEquals( $second_post_id, $results['data']['posts']['edges'][0]['node']['postId'] );
$this->assertEquals( $expected_cursor, $results['data']['posts']['edges'][0]['cursor'] );
$this->assertEquals( $expected_cursor, $results['data']['posts']['pageInfo']['startCursor'] );
$this->assertEquals( $expected_cursor, $results['data']['posts']['pageInfo']['endCursor'] );
}
public function backwardPagination( $cursor ) {
$variables = [
'last' => 1,
'before' => $cursor,
];
$results = $this->postsQuery( $variables );
$second_to_last_post = new WP_Query( [
'posts_per_page' => 1,
'paged' => 2,
'order' => 'ASC',
] );
$second_to_last_post_id = $second_to_last_post->posts[0]->ID;
$expected_cursor = \GraphQLRelay\Connection\ArrayConnection::offsetToCursor( $second_to_last_post_id );
$this->assertNotEmpty( $results );
$this->assertEquals( 1, count( $results['data']['posts']['edges'] ) );
$this->assertEquals( $second_to_last_post_id, $results['data']['posts']['edges'][0]['node']['postId'] );
$this->assertEquals( $expected_cursor, $results['data']['posts']['edges'][0]['cursor'] );
$this->assertEquals( $expected_cursor, $results['data']['posts']['pageInfo']['startCursor'] );
$this->assertEquals( $expected_cursor, $results['data']['posts']['pageInfo']['endCursor'] );
}
public function testMaxQueryAmount() {
$variables = [
'first' => 150,
];
$results = $this->postsQuery( $variables );
$this->assertNotEmpty( $results );
/**
* The max that can be queried by default is 100 items
*/
$this->assertCount( 100, $results['data']['posts']['edges'] );
$this->assertTrue( $results['data']['posts']['pageInfo']['hasNextPage'] );
/**
* Test the filter to make sure it's capping the results properly
*/
add_filter( 'graphql_connection_max_query_amount', function() {
return 20;
} );
$variables = [
'first' => 150,
];
$results = $this->postsQuery( $variables );
add_filter( 'graphql_connection_max_query_amount', function() {
return 100;
} );
$this->assertCount( 20, $results['data']['posts']['edges'] );
$this->assertTrue( $results['data']['posts']['pageInfo']['hasNextPage'] );
}
public function testPostHasPassword() {
// Create a test post with a password
$this->createPostObject( [
'post_title' => 'Password protected',
'post_type' => 'post',
'post_status' => 'publish',
'post_password' => 'password',
] );
/**
* WP_Query posts with a password
*/
$wp_query_posts_with_password = new WP_Query( [
'has_password' => true,
] );
/**
* GraphQL query posts that have a password
*/
$variables = [
'where' => [
'hasPassword' => true,
],
];
$request = $this->postsQuery( $variables );
$this->assertNotEmpty( $request );
$this->assertArrayNotHasKey( 'errors', $request );
$edges = $request['data']['posts']['edges'];
$this->assertNotEmpty( $edges );
/**
* Loop through all the returned posts
*/
foreach ( $edges as $edge ) {
/**
* Assert that all posts returned have a password, since we queried for
* posts using "has_password => true"
*/
$password = get_post( $edge['node']['postId'] )->post_password;
$this->assertNotEmpty( $password );
}
}
public function testPageWithChildren() {
$parent_id = $this->factory->post->create( [
'post_type' => 'page'
] );
$child_id = $this->factory->post->create( [
'post_type' => 'page',
'post_parent' => $parent_id
] );
$global_id = \GraphQLRelay\Relay::toGlobalId( 'page', $parent_id );
$global_child_id = \GraphQLRelay\Relay::toGlobalId( 'page', $child_id );
$query = '
{
page( id: "' . $global_id . '" ) {
id
pageId
childPages {
edges {
node {
id
pageId
}
}
}
}
}
';
$actual = do_graphql_request( $query );
/**
* Make sure the query didn't return any errors
*/
$this->assertArrayNotHasKey( 'errors', $actual );
$parent = $actual['data']['page'];
$child = $parent['childPages']['edges'][0]['node'];
/**
* Make sure the child and parent data matches what we expect
*/
$this->assertEquals( $global_id, $parent['id'] );
$this->assertEquals( $parent_id, $parent['pageId'] );
$this->assertEquals( $global_child_id, $child['id'] );
$this->assertEquals( $child_id, $child['pageId'] );
}
public function testSanitizeInputFieldsAuthorArgs() {
$mock_args = [
'authorName' => 'testAuthorName',
'authorIn' => [ 1, 2, 3 ],
'authorNotIn' => [ 4, 5, 6 ],
];
$actual = \WPGraphQL\Type\PostObject\Connection\PostObjectConnectionResolver::sanitize_input_fields( $mock_args, null, [], $this->app_context, $this->app_info );
/**
* Make sure the returned values are equal to mock args
*/
$this->assertEquals( 'testAuthorName', $actual['author_name'] );
$this->assertEquals( [ 1, 2, 3 ], $actual['author__in'] );
$this->assertEquals( [ 4, 5, 6 ], $actual['author__not_in'] );
/**
* Make sure the query didn't return these array values
*/
$this->assertArrayNotHasKey( 'authorName', $actual );
$this->assertArrayNotHasKey( 'authorIn', $actual );
$this->assertArrayNotHasKey( 'authorNotIn', $actual );
}
public function testSanitizeInputFieldsCategoryArgs() {
$mock_args = [
'categoryId' => 1,
'categoryName' => 'testCategory',
'categoryIn' => [ 4, 5, 6 ],
];
$actual = \WPGraphQL\Type\PostObject\Connection\PostObjectConnectionResolver::sanitize_input_fields( $mock_args, null, [], $this->app_context, $this->app_info );
/**
* Make sure the returned values are equal to mock args
*/
$this->assertEquals( 1, $actual['cat'] );
$this->assertEquals( 'testCategory', $actual['category_name'] );
$this->assertEquals( [ 4, 5, 6 ], $actual['category__in'] );
/**
* Make sure the query didn't return these array values
*/
$this->assertArrayNotHasKey( 'categoryId', $actual );
$this->assertArrayNotHasKey( 'categoryName', $actual );
$this->assertArrayNotHasKey( 'categoryIn', $actual );
}
public function testSanitizeInputFieldsTagArgs() {
$mock_args = [
'tagId' => 1,
'tagIds' => [ 1, 2, 3 ],
'tagSlugAnd' => [ 4, 5, 6 ],
'tagSlugIn' => [ 6, 7, 8 ],
];
$actual = \WPGraphQL\Type\PostObject\Connection\PostObjectConnectionResolver::sanitize_input_fields( $mock_args, null, [], $this->app_context, $this->app_info );
/**
* Make sure the returned values are equal to mock args
*/
$this->assertEquals( 1, $actual['tag_id'] );
$this->assertEquals( [ 1, 2, 3 ], $actual['tag__and'] );
$this->assertEquals( [ 4, 5, 6 ], $actual['tag_slug__and'] );
$this->assertEquals( [ 6, 7, 8 ], $actual['tag_slug__in'] );
/**
* Make sure the query didn't return these array values
*/
$this->assertArrayNotHasKey( 'tagId', $actual );
$this->assertArrayNotHasKey( 'tagIds', $actual );
$this->assertArrayNotHasKey( 'tagSlugAnd', $actual );
$this->assertArrayNotHasKey( 'tagSlugIn', $actual );
}
public function testSanitizeInputFieldsSearchArgs() {
$mock_args = [
'search' => 'testSearchString',
'id' => 1,
];
$actual = \WPGraphQL\Type\PostObject\Connection\PostObjectConnectionResolver::sanitize_input_fields( $mock_args, null, [], $this->app_context, $this->app_info );
/**
* Make sure the returned values are equal to mock args
*/
$this->assertEquals( 'testSearchString', $actual['s'] );
$this->assertEquals( 1, $actual['p'] );
/**
* Make sure the query didn't return these array values
*/
$this->assertArrayNotHasKey( 'search', $actual );
$this->assertArrayNotHasKey( 'id', $actual );
}
public function testSanitizeInputFieldsParentArgs() {
$mock_args = [
'parent' => 2,
'parentIn' => [ 3, 4, 5 ],
'parentNotIn' => [ 6, 7, 8 ],
'in' => [ 9, 10, 11 ],
'notIn' => [ 12, 13, 14 ],
'nameIn' => [ 'testPost1', 'testPost2', 'testPost3' ],
];
$actual = \WPGraphQL\Type\PostObject\Connection\PostObjectConnectionResolver::sanitize_input_fields( $mock_args, null, [], $this->app_context, $this->app_info );
/**
* Make sure the returned values are equal to mock args
*/
$this->assertEquals( 2, $actual['post_parent'] );
$this->assertEquals( [ 3, 4, 5 ], $actual['post_parent__in'] );
$this->assertEquals( [ 6, 7, 8 ], $actual['post_parent__not_in'] );
$this->assertEquals( [ 9, 10, 11 ], $actual['post__in'] );
$this->assertEquals( [ 12, 13, 14 ], $actual['post__not_in'] );
$this->assertEquals( [ 'testPost1', 'testPost2', 'testPost3' ], $actual['post_name__in'] );
/**
* Make sure the query didn't return these array values
*/
$this->assertArrayNotHasKey( 'parent', $actual );
$this->assertArrayNotHasKey( 'parentIn', $actual );
$this->assertArrayNotHasKey( 'parentNotIn', $actual );
$this->assertArrayNotHasKey( 'in', $actual );
$this->assertArrayNotHasKey( 'notIn', $actual );
$this->assertArrayNotHasKey( 'nameIn', $actual );
}
public function testSanitizeInputFieldsMiscArgs() {
$mock_args = [
'hasPassword' => true,
'password' => 'myPostPassword123',
'status' => 'publish',
'dateQuery' => array(
array(
'year' => 2012,
'month' => 12,
'day' => 12,
),
),
];
$actual = \WPGraphQL\Type\PostObject\Connection\PostObjectConnectionResolver::sanitize_input_fields( $mock_args, null, [], $this->app_context, $this->app_info );
/**
* Make sure the returned values are equal to mock args
*/
$this->assertTrue( $actual['has_password'] );
$this->assertEquals( 'myPostPassword123', $actual['post_password'] );
$this->assertEquals( 'publish', $actual['post_status'] );
$this->assertEquals(
array(
array(
'year' => 2012,
'month' => 12,
'day' => 12,
),
)
, $actual['date_query'] );
/**
* Make sure the query didn't return these array values
*/
$this->assertArrayNotHasKey( 'hasPassword', $actual );
$this->assertArrayNotHasKey( 'password', $actual );
$this->assertArrayNotHasKey( 'status', $actual );
$this->assertArrayNotHasKey( 'dateQuery', $actual );
}
public function testSanitizeInputFieldsListOfPostStatusEnum() {
$mock_args = [
'stati' => [ 'publish', 'private' ],
];
$actual = \WPGraphQL\Type\PostObject\Connection\PostObjectConnectionResolver::sanitize_input_fields( $mock_args, null, [], $this->app_context, $this->app_info );
/**
* Make sure the returned values are equal to mock args
*/
$this->assertEquals( ['publish', 'private'], $actual['post_status'] );
/**
* Make sure the query didn't return these array values
*/
$this->assertArrayNotHasKey( 'status', $actual );
}
/**
* @group get_query_args
*/
public function testGetQueryArgs() {
/**
* Mock args
*/
$mock_args = array(
'orderby' => 'DESC',
'where' => array(
'orderby' => array(
array(
'field' => 'author',
'order' => 'ASC',
),
),
),
);
/**
* Create post
*/
$test_post = $this->factory->post->create();
$source = get_post( $test_post );
/**
* New page
*/
$actual = new \WPGraphQL\Type\PostObject\Connection\PostObjectConnectionResolver( 'page' );
$actual = $actual::get_query_args( $source, $mock_args, $this->app_context, $this->app_info );
/**
* Expected result
*/
$expected = array(
'post_type' => 'page',
'no_found_rows' => true,
'post_status' => 'publish',
'posts_per_page' => 11,
'post_parent' => $test_post,
'graphql_cursor_offset' => 0,
'graphql_cursor_compare' => '<',
'graphql_args' => array(
'orderby' => 'DESC',
'where' => array(
'orderby' => array(
0 => array(
'field' => 'author',
'order' => 'ASC',
)
),
),
),
'orderby' => array(
'author' => 'ASC',
),
);
/**
* Make sure the expected result is equal to the response of $actual
*/
$this->assertEquals( $expected, $actual );
}
/**
* @group get_query_args
*/
public function testGetQueryArgsAttachment() {
/**
* Mock args
*/
$mock_args = array(
'post_status' => 'publish',
);
/**
* Create attachment
*/
$child_id = $this->factory->post->create( [
'post_type' => 'attachment',
] );
$post_type = 'attachment';
$source = get_post( $child_id );
/**
* New post type attachment
*/
$actual = new \WPGraphQL\Type\PostObject\Connection\PostObjectConnectionResolver( $post_type );
$actual = $actual->get_query_args( $source, $mock_args, $this->app_context, $this->app_info );
/**
* Make sure the post status is equal to inherit
*/
$this->assertEquals( 'inherit', $actual['post_status'] );
/**
* Make sure get_query_args is setting the post id as post_parent
*/
$this->assertEquals( $child_id, $actual['post_parent'] );
}
/**
* @group get_query_args
*/
public function testGetQueryArgsPostType() {
/**
* Get post type object
*/
$source = get_post_type_object( 'post' );
$mock_args = array();
$actual = \WPGraphQL\Type\PostObject\Connection\PostObjectConnectionResolver::get_query_args( $source, $mock_args, $this->app_context, $this->app_info );
/**
* Make sure that post type is equals to post
*/
$this->assertEquals( 'post', $actual['post_type'] );
}
/**
* @group get_query_args
*/
public function testGetQueryArgsUser() {
/**
* Create a user
*/
$user_id = $this->factory->user->create();
$source = get_user_by( 'ID', $user_id );
$mock_args = array();
$actual = \WPGraphQL\Type\PostObject\Connection\PostObjectConnectionResolver::get_query_args( $source, $mock_args, $this->app_context, $this->app_info );
/**
* Make sure the author is equal to the user previously created
*/
$this->assertEquals( $user_id, $actual['author'] );
}
}