Refactor down to two concepts - settings groups and settings. Fix up tests, and start working on returning actual settings and their values.

This commit is contained in:
Justin Shreve 2016-03-23 12:36:59 -07:00
parent f425a3735a
commit fa5425109e
3 changed files with 284 additions and 236 deletions

View File

@ -26,23 +26,31 @@ class WC_Rest_Settings_Controller extends WP_Rest_Controller {
* @since 2.7.0
*/
public function register_routes() {
register_rest_route( WC_API::REST_API_NAMESPACE, '/' . $this->rest_base . '/locations', array(
register_rest_route( WC_API::REST_API_NAMESPACE, '/' . $this->rest_base, array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_locations' ),
'callback' => array( $this, 'get_groups' ),
'permission_callback' => array( $this, 'permissions_check' ),
'args' => $this->get_locations_params(),
),
'schema' => array( $this, 'get_location_schema' ),
'schema' => array( $this, 'group_schema' ),
) );
register_rest_route( WC_API::REST_API_NAMESPACE, '/' . $this->rest_base . '/locations/(?P<location>[\w-]+)', array(
register_rest_route( WC_API::REST_API_NAMESPACE, '/' . $this->rest_base . '/(?P<group>[\w-]+)', array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_location' ),
'callback' => array( $this, 'get_group' ),
'permission_callback' => array( $this, 'permissions_check' ),
),
'schema' => array( $this, 'get_location_schema' ),
'schema' => array( $this, 'group_schema' ),
) );
// @todo change this to support settings with array keys / multiple values?
register_rest_route( WC_API::REST_API_NAMESPACE, '/' . $this->rest_base . '/(?P<group>[\w-]+)/(?P<setting>[\w-]+)', array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_setting' ),
'permission_callback' => array( $this, 'permissions_check' ),
),
'schema' => array( $this, 'setting_schema' ),
) );
}
@ -54,7 +62,7 @@ class WC_Rest_Settings_Controller extends WP_Rest_Controller {
*/
public function permissions_check( $request ) {
if ( ! current_user_can( 'manage_options' ) ) {
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot access settings.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
//return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot access settings.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
}
return true;
@ -62,135 +70,112 @@ class WC_Rest_Settings_Controller extends WP_Rest_Controller {
/*
|--------------------------------------------------------------------------
| /settings/locations
| /settings
|--------------------------------------------------------------------------
| Returns a list of "settings" locations so all settings for a particular page
| or location can be properly loaded.
| Returns a list of "settings" groups so all settings for a particular page
| or section can be properly loaded.
*/
/**
* Get all settings locations.
* Get all settings groups.
* @since 2.7.0
* @param WP_REST_Request $request Full details about the request.
* @param WP_REST_Request $request
* @return WP_Error|WP_REST_Response
*/
public function get_locations( $request ) {
$locations = apply_filters( 'woocommerce_settings_locations', array() );
$defaults = $this->get_location_defaults();
$filtered_locations = array();
foreach ( $locations as $location ) {
$location = wp_parse_args( $location, $defaults );
$location_valid = true;
if ( is_null( $location['id'] ) || is_null( $location['label'] ) || is_null( $location['type'] ) ) { // id, label, and type are required fields
$location_valid = false;
} else if ( ! empty( $request['type'] ) ) {
if ( in_array( $request['type'], $this->get_location_types() ) && $request['type'] !== $location['type'] ) {
$location_valid = false;
}
}
public function get_groups( $request ) {
$groups = apply_filters( 'woocommerce_settings_groups', array() );
if ( empty( $groups ) ) {
return new WP_Error( 'rest_setting_groups_empty', __( 'No setting groups have been registered.', 'woocommerce' ), array( 'status' => 500 ) );
}
if ( $location_valid ) {
$filtered_locations[] = array_intersect_key(
$location,
array_flip( array_filter( array_keys( $location ), array( $this, 'filter_location_keys' ) ) )
);
$defaults = $this->group_defaults();
$filtered_groups = array();
foreach ( $groups as $group ) {
$group = wp_parse_args( $group, $defaults );
if ( ! is_null( $group['id'] ) && ! is_null( $group['label'] ) ) {
$filtered_groups[] = $this->filter_group( $group );
}
}
$response = rest_ensure_response( $filtered_locations );
$response = rest_ensure_response( $filtered_groups );
return $response;
}
/**
* Return a single setting location.
* Return a single setting group and its settings.
* @since 2.7.0
* @param WP_REST_Request $request Full details about the request.
* @param WP_REST_Request $request
* @return WP_Error|WP_REST_Response
*/
public function get_location( $request ) {
$locations = apply_filters( 'woocommerce_settings_locations', array() );
if ( empty( $locations ) ) {
return new WP_Error( 'rest_setting_location_invalid_id', __( 'Invalid location id.' ), array( 'status' => 404 ) );
public function get_group( $request ) {
$groups = apply_filters( 'woocommerce_settings_groups', array() );
if ( empty( $groups ) ) {
return new WP_Error( 'rest_setting_group_invalid', __( 'Invalid setting group.', 'woocommerce' ), array( 'status' => 404 ) );
}
$index_key = $this->get_array_key_from_location_id( $locations, $request['location'] );
if ( is_null( $index_key ) || empty( $locations[ $index_key ] ) ) {
return new WP_Error( 'rest_setting_location_invalid_id', __( 'Invalid location id.' ), array( 'status' => 404 ) );
$index_key = array_keys( wp_list_pluck( $groups, 'id' ), $request['group'] );
if ( empty( $index_key ) || empty( $groups[ $index_key[0] ] ) ) {
return new WP_Error( 'rest_setting_group_invalid', __( 'Invalid setting group.' ), array( 'status' => 404 ) );
}
$location = $locations[ $index_key ];
$defaults = $this->get_location_defaults();
$location = wp_parse_args( $location, $defaults );
if ( is_null( $location['id'] ) || is_null( $location['label'] ) || is_null( $location['type'] ) ) {
return new WP_Error( 'rest_setting_location_invalid_id', __( 'Invalid location id.' ), array( 'status' => 404 ) );
$group = wp_parse_args( $groups[ $index_key[0] ], $this->group_defaults() );
if ( is_null( $group['id'] ) || is_null( $group['label'] ) ) {
return new WP_Error( 'rest_setting_group_invalid', __( 'Invalid setting group.' ), array( 'status' => 404 ) );
}
if ( 'page' === $location['type'] ) {
$location['groups'] = array();
$groups = apply_filters( 'woocommerce_settings_groups_' . $location['id'], array() );
if ( ! empty( $groups ) ) {
foreach ( $groups as $group ) {
$location['groups'][] = array_intersect_key(
$group,
array_flip( array_filter( array_keys( $group ), array( $this, 'filter_group_keys' ) ) )
);
$filtered_group = $this->filter_group( $group );
$filtered_group['settings'] = array();
$settings = apply_filters( 'woocommerce_settings_' . $group['id'], array() );
if ( ! empty( $settings ) ) {
foreach ( $settings as $setting ) {
$setting = $this->filter_setting( $setting );
$setting['value'] = $this->get_value( $setting['id'] );
if ( $this->is_valid_type( $setting['type'] ) ) {
$filtered_group['settings'][] = $setting;
}
}
}
$filtered_location = array_intersect_key(
$location,
array_flip( array_filter( array_keys( $location ), array( $this, 'filter_location_keys' ) ) )
);
$response = rest_ensure_response( $filtered_location );
return $response;
return rest_ensure_response( $filtered_group );
}
/**
* Callback for allowed keys for each location response.
* Return a single setting.
* @since 2.7.0
* @param string $key Key to check
* @return boolean
* @param WP_REST_Request $request
* @return WP_Error|WP_REST_Response
*/
public function filter_location_keys( $key ) {
return in_array( $key, array( 'id', 'type', 'label', 'description', 'groups' ) );
public function get_setting( $request ) {
if ( empty( $request['group'] ) || empty( $request['setting'] ) ) {
return new WP_Error( 'rest_setting_setting_invalid', __( 'Invalid setting.' ), array( 'status' => 404 ) );
}
$settings = apply_filters( 'woocommerce_settings_' . $request['group'], array() );
$array_key = array_keys( wp_list_pluck( $settings, 'id' ), $request['setting'] );
if ( empty( $array_key ) ) {
return new WP_Error( 'rest_setting_setting_invalid', __( 'Invalid setting.' ), array( 'status' => 404 ) );
}
$setting = $this->filter_setting( $settings[ $array_key[0] ] );
$setting['value'] = $this->get_value( $setting['id'] );
if ( ! $this->is_valid_type( $setting['type'] ) ) {
return new WP_Error( 'rest_setting_setting_invalid', __( 'Invalid setting.' ), array( 'status' => 404 ) );
}
return rest_ensure_response( $setting );
}
/**
* Callback for allowed keys for each group.
* @since 2.7.0
* @param string $key Key to check
* @return boolean
*/
public function filter_group_keys( $key ) {
return in_array( $key, array( 'id', 'label', 'description' ) );
}
/**
* Get supported query parameters for locations.
* Get the groups schema, conforming to JSON Schema.
* @since 2.7.0
* @return array
*/
public function get_locations_params() {
$query_params = array();
$query_params['type'] = array(
'description' => __( 'Limit result set to setting locations of a specific type.', 'woocommerce' ),
'type' => 'string'
);
return $query_params;
}
/**
* Get the locations chema, conforming to JSON Schema.
* @since 2.7.0
* @return array
*/
public function get_location_schema() {
public function group_schema() {
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'settings-locations',
'title' => 'settings-group',
'type' => 'object',
'properties' => array(
'id' => array(
@ -200,13 +185,6 @@ class WC_Rest_Settings_Controller extends WP_Rest_Controller {
'sanitize_callback' => 'sanitize_title',
),
),
'type' => array(
'description' => __( 'Context for where the settings in this location are going to be displayed.' ),
'type' => 'string',
'arg_options' => array(
'sanitize_callback' => 'sanitize_title',
),
),
'label' => array(
'description' => __( 'A human readable label. This is a translated string that can be used in interfaces.' ),
'type' => 'string',
@ -221,6 +199,13 @@ class WC_Rest_Settings_Controller extends WP_Rest_Controller {
'sanitize_callback' => 'sanitize_text_field',
),
),
'parent_id' => array(
'description' => __( 'ID of parent grouping.' ),
'type' => 'string',
'arg_options' => array(
'sanitize_callback' => 'sanitize_text_field',
),
),
),
);
@ -228,44 +213,137 @@ class WC_Rest_Settings_Controller extends WP_Rest_Controller {
}
/**
* Returns a list of allowed setting location types.
* @todo move this?
* Get a value from WP's settings API.
* @since 2.7.0
* @return array
* @param string $setting
* @param string $default
* @return mixed
*/
protected function get_location_types() {
return apply_filters( 'woocommerce_settings_location_types', array( 'page', 'metabox', 'shipping-zone' ) );
public function get_value( $setting, $default = '' ) {
if ( strstr( $setting, '[' ) ) { // Array value
parse_str( $setting, $setting_array );
$setting = current( array_keys( $setting ) );
$values = get_option( $setting, '' );
$key = key( $setting_array[ $setting ] );
if ( isset( $values[ $key ] ) ) {
$value = $values[ $key ];
} else {
$value = null;
}
} else { // Single value
$value = get_option( $setting, null );
}
if ( is_array( $setting ) ) {
$value = array_map( 'stripslashes', $value );
} elseif ( ! is_null( $value ) ) {
$value = stripslashes( $value );
}
return $value === null ? $default : $value;
}
/**
* Returns default settings for the various locations. null means the field is required.
* @todo move this?
* @since 2.7.0
* Filters out bad values from the groups array/filter so we
* only return known values via the API.
* @since 2.7.0
* @param array $group
* @return array
*/
protected function get_location_defaults() {
return array(
'id' => null,
'type' => 'page',
'label' => null,
'description' => '',
public function filter_group( $group ) {
return array_intersect_key(
$group,
array_flip( array_filter( array_keys( $group ), array( $this, 'allowed_group_keys' ) ) )
);
}
/**
* Returns the array key for a specific location ID so it can be pulled out of the 'locations' array.
* @todo move this?
* @param array $locations woocommerce_settings_locations
* @param string $id Location ID to get an array key index for
* @return integer|null
* Filters out bad values from the settings array/filter so we
* only return known values via the API.
* @since 2.7.0
* @param array $setting
* @return array
*/
protected function get_array_key_from_location_id( $locations, $id ) {
foreach ( $locations as $key => $location ) {
if ( ! empty( $location['id'] ) && $id === $location['id'] ) {
return $key;
}
public function filter_setting( $setting ) {
$setting = array_intersect_key(
$setting,
array_flip( array_filter( array_keys( $setting ), array( $this, 'allowed_setting_keys' ) ) )
);
if ( empty( $setting['options'] ) ) {
unset( $setting['options'] );
}
return null;
return $setting;
}
/**
* Callback for allowed keys for each group response.
* @since 2.7.0
* @param string $key Key to check
* @return boolean
*/
public function allowed_group_keys( $key ) {
return in_array( $key, array( 'id', 'label', 'description', 'parent_id' ) );
}
/**
* Callback for allowed keys for each setting response.
* @since 2.7.0
* @param string $key Key to check
* @return boolean
*/
public function allowed_setting_keys( $key ) {
return in_array( $key, array(
'id', 'label', 'description', 'default', 'tip',
'placeholder', 'type', 'options', 'value',
) );
}
/**
* Boolean for if a setting type is a valid supported setting type.
* @since 2.7.0
* @param string $type
* @return boolean
*/
public function is_valid_type( $type ) {
return in_array( $type, array(
'text', 'email', 'number', 'color', 'password',
'textarea', 'select', 'multiselect', 'radio', 'checkbox',
) );
}
/**
* Returns default settings for groups. null means the field is required.
* @since 2.7.0
* @return array
*/
protected function group_defaults() {
return array(
'id' => null,
'label' => null,
'description' => '',
'parent_id' => '',
);
}
/**
* Returns default settings for settings. null means the field is required.
* @since 2.7.0
* @return array
*/
protected function setting_defaults() {
return array(
'id' => null,
'label' => null,
'type' => null,
'description' => '',
'tip' => '',
'placeholder' => '',
'default' => '',
'options' => array(),
'value' => '',
);
}
}

View File

@ -12,60 +12,74 @@ class WC_Helper_Settings {
* @since 2.7.0
*/
public static function register() {
add_filter( 'woocommerce_settings_locations', array( 'WC_Helper_Settings', 'register_locations' ) );
add_filter( 'woocommerce_settings_groups_test', array( 'WC_Helper_Settings', 'register_test_groups' ) );
add_filter( 'woocommerce_settings_groups', array( 'WC_Helper_Settings', 'register_groups' ) );
add_filter( 'woocommerce_settings_test', array( 'WC_Helper_Settings', 'register_test_settings' ) );
}
/**
* Registers some example locations, including invalid ones that should not show up in JSON responses.
* Registers some example setting groups, including invalid ones that should not show up in JSON responses.
* @since 2.7.0
* @param array $locations
* @param array $groups
* @return array
*/
public static function register_locations( $locations ) {
$locations[] = array(
public static function register_groups( $groups ) {
$groups[] = array(
'id' => 'test',
'type' => 'page',
'bad' => 'value',
'label' => __( 'Test Extension', 'woocommerce' ),
'description' => __( 'My awesome test settings.', 'woocommerce' ),
);
$locations[] = array(
$groups[] = array(
'id' => 'test-2',
'type' => 'page',
'label' => __( 'Test Extension', 'woocommerce' ),
'description' => '',
);
$locations[] = array(
$groups[] = array(
'id' => 'coupon-data',
'type' => 'metabox',
'label' => __( 'Coupon Data', 'woocommerce' ),
);
$locations[] = array(
'label' => __( 'Invalid', 'woocommerce' ),
);
$locations[] = array(
$groups[] = array(
'id' => 'invalid',
);
return $locations;
}
/**
* Registers some example groups for the 'test' page.
* @since 2.7.0
* @param array $groups
* @return array
*/
public static function register_test_groups( $groups ) {
$groups[] = array(
'id' => 'general',
'label' => __( 'General', 'woocommerce' ),
);
$groups[] = array(
'id' => 'inventory',
'label' => __( 'Inventory', 'woocommerce' ),
);
return $groups;
}
/**
* Registers some example settings.
* @since 2.7.0
* @param array $settings
* @return array
*/
public static function register_settings( $settings ) {
$settings[] = array(
'id' => 'catalog_options',
'label' => __( 'Shop & Product Pages', 'woocommerce' ),
'type' => 'title',
);
$settings[] = array(
'id' => 'woocommerce_shop_page_display',
'label' => __( 'Shop Page Display', 'woocommerce' ),
'description' => __( 'This controls what is shown on the product archive.', 'woocommerce' ),
'default' => '',
'type' => 'select',
'options' => array(
'' => __( 'Show products', 'woocommerce' ),
'subcategories' => __( 'Show categories &amp; subcategories', 'woocommerce' ),
'both' => __( 'Show both', 'woocommerce' ),
),
);
$settings[] = array(
'id' => 'woocommerce_enable_lightbox',
'label' => __( 'Product Image Gallery', 'woocommerce' ),
'description' => __( 'Enable Lightbox for product images', 'woocommerce' ),
'default' => 'yes',
'tip' => __( 'Product gallery images will open in a lightbox.', 'woocommerce' ),
'type' => 'checkbox',
);
return $settings;
}
}

View File

@ -40,57 +40,58 @@ class Settings extends \WC_Unit_Test_Case {
*/
public function test_register_routes() {
$routes = $this->server->get_routes();
$this->assertArrayHasKey( '/wc/v1/settings/locations', $routes );
$this->assertArrayHasKey( '/wc/v1/settings', $routes );
// @todo test others
}
/**
* Test getting all locations.
* Test getting all groups.
* @since 2.7.0
*/
public function test_get_locations() {
public function test_get_groups() {
wp_set_current_user( $this->user );
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/locations' ) );
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings' ) );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 3, count( $data ) );
$this->check_get_location_response( $data[0], array(
$this->check_get_group_response( $data[0], array(
'id' => 'test',
'type' => 'page',
'label' => 'Test Extension',
'parent_id' => '',
'description' => 'My awesome test settings.',
) );
$this->check_get_location_response( $data[2], array(
$this->check_get_group_response( $data[2], array(
'id' => 'coupon-data',
'type' => 'metabox',
'label' => 'Coupon Data',
'parent_id' => '',
'description' => '',
) );
}
/**
* Test /settings/locations without valid permissions/creds.
* Test /settings without valid permissions/creds.
* @since 2.7.0
*/
public function test_get_locations_without_permission() {
public function test_get_groups_without_permission() {
wp_set_current_user( 0 );
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/locations' ) );
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings' ) );
$this->assertEquals( 401, $response->get_status() );
}
/**
* Test /settings/locations correctly filters out bad values.
* Test /settings/ correctly filters out bad values.
* Handles required fields and bogus fields.
* @since 2.7.0
*/
public function test_get_locations_correctly_filters_values() {
public function test_get_groups_correctly_filters_values() {
wp_set_current_user( $this->user );
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/locations' ) );
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings' ) );
$data = $response->get_data();
$this->assertEquals( 'test', $data[0]['id'] );
@ -98,119 +99,74 @@ class Settings extends \WC_Unit_Test_Case {
}
/**
* Test /settings/locations with type.
* Test /settings schema.
* @since 2.7.0
*/
public function test_get_locations_with_type() {
wp_set_current_user( $this->user );
$request = new \WP_REST_Request( 'GET', '/wc/v1/settings/locations' );
$request->set_param( 'type', 'not-a-real-type' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 3, count( $data ) ); // all results
$request = new \WP_REST_Request( 'GET', '/wc/v1/settings/locations' );
$request->set_param( 'type', 'page' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 2, count( $data ) );
}
/**
* Test /settings/locations schema.
* @since 2.7.0
*/
public function test_get_location_schema() {
$request = new \WP_REST_Request( 'OPTIONS', '/wc/v1/settings/locations' );
public function test_get_group_schema() {
$request = new \WP_REST_Request( 'OPTIONS', '/wc/v1/settings' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$properties = $data['schema']['properties'];
$this->assertEquals( 4, count( $properties ) );
$this->assertArrayHasKey( 'id', $properties );
$this->assertArrayHasKey( 'type', $properties );
$this->assertArrayHasKey( 'parent_id', $properties );
$this->assertArrayHasKey( 'label', $properties );
$this->assertArrayHasKey( 'description', $properties );
}
/**
* Test getting a single location item.
* Test getting a single group.
* @since 2.7.0
*/
public function test_get_location() {
public function test_get_group() {
wp_set_current_user( $this->user );
// test getting a location that does not exist
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/locations/not-real' ) );
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/not-real' ) );
$data = $response->get_data();
$this->assertEquals( 404, $response->get_status() );
// test getting the 'invalid' location
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/locations/invalid' ) );
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/invalid' ) );
$data = $response->get_data();
$this->assertEquals( 404, $response->get_status() );
// test getting a valid location
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/locations/coupon-data' ) );
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/coupon-data' ) );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->check_get_location_response( $data, array(
$this->check_get_group_response( $data, array(
'id' => 'coupon-data',
'type' => 'metabox',
'label' => 'Coupon Data',
'parent_id' => '',
'description' => '',
) );
// @todo make sure settings are set correctly
}
/**
* Test getting a single location item.
* Test getting a single group without permission.
* @since 2.7.0
*/
public function test_get_location_without_permission() {
public function test_get_group_without_permission() {
wp_set_current_user( 0 );
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/locations/coupon-data' ) );
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/coupon-data' ) );
$this->assertEquals( 401, $response->get_status() );
}
/**
* Test settings groups (for pages)
* @since 2.7.0
*/
public function test_settings_groups() {
wp_set_current_user( $this->user );
// test getting a non page location
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/locations/coupon-data' ) );
$data = $response->get_data();
$this->assertArrayNotHasKey( 'groups', $data );
// test getting a page with no groups
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/locations/test-2' ) );
$data = $response->get_data();
$this->assertArrayHasKey( 'groups', $data );
$this->assertEmpty( $data['groups'] );
// test getting a page with groups
$response = $this->server->dispatch( new \WP_REST_Request( 'GET', '/wc/v1/settings/locations/test' ) );
$data = $response->get_data();
$this->assertArrayHasKey( 'groups', $data );
$this->assertEquals( 2, count( $data['groups'] ) );
}
/**
* Ensure valid location data response.
* @since 2.7.0
* @param array $response
* @param array $expected
*/
protected function check_get_location_response( $response, $expected ) {
protected function check_get_group_response( $response, $expected ) {
$this->assertEquals( $expected['id'], $response['id'] );
$this->assertEquals( $expected['type'], $response['type'] );
$this->assertEquals( $expected['parent_id'], $response['parent_id'] );
$this->assertEquals( $expected['label'], $response['label'] );
$this->assertEquals( $expected['description'], $response['description'] );
}