diff --git a/includes/Modules/Analytics_4.php b/includes/Modules/Analytics_4.php index c6bc99cef29..c8c1c306d3c 100644 --- a/includes/Modules/Analytics_4.php +++ b/includes/Modules/Analytics_4.php @@ -73,11 +73,15 @@ use Google\Site_Kit\Modules\Analytics_4\Datapoints\Get_Container_Lookup; use Google\Site_Kit\Modules\Analytics_4\Datapoints\Get_Container_Destinations; use Google\Site_Kit\Modules\Analytics_4\Datapoints\Get_Enhanced_Measurement_Settings; +use Google\Site_Kit\Modules\Analytics_4\Datapoints\Get_Google_Tag_Settings; use Google\Site_Kit\Modules\Analytics_4\Datapoints\Get_Webdatastreams; use Google\Site_Kit\Modules\Analytics_4\Datapoints\Get_Webdatastreams_Batch; use Google\Site_Kit\Modules\Analytics_4\Datapoints\Save_Audience_Settings; use Google\Site_Kit\Modules\Analytics_4\Datapoints\Sync_Audiences; use Google\Site_Kit\Modules\Analytics_4\Datapoints\Save_Custom_Dimension_Data_Available; +use Google\Site_Kit\Modules\Analytics_4\Datapoints\Save_Resource_Data_Availability_Date; +use Google\Site_Kit\Modules\Analytics_4\Datapoints\Set_Google_Tag_ID_Mismatch; +use Google\Site_Kit\Modules\Analytics_4\Datapoints\Set_Is_Web_Data_Stream_Unavailable; use Google\Site_Kit\Modules\Analytics_4\Datapoints\Sync_Custom_Dimensions; use Google\Site_Kit\Modules\Analytics_4\Datapoints\Update_Enhanced_Measurement_Settings; use Google\Site_Kit\Modules\Analytics_4\Synchronize_Property; @@ -103,7 +107,6 @@ use Google\Site_Kit_Dependencies\Google\Service\GoogleAnalyticsAdmin\GoogleAnalyticsAdminV1betaProperty as Google_Service_GoogleAnalyticsAdmin_GoogleAnalyticsAdminV1betaProperty; use Google\Site_Kit_Dependencies\Google\Service\GoogleAnalyticsAdminV1alpha; use Google\Site_Kit_Dependencies\Google\Service\TagManager as Google_Service_TagManager; -use Google\Site_Kit_Dependencies\Google\Service\TagManager\Container as Google_Service_TagManager_Container; use Google\Site_Kit_Dependencies\Psr\Http\Message\RequestInterface; use Google\Site_Kit\Core\REST_API\REST_Routes; use Google\Site_Kit\Core\Tracking\Feature_Metrics_Trait; @@ -742,11 +745,15 @@ protected function get_datapoint_definitions() { 'request_scopes_message' => __( 'You’ll need to grant Site Kit permission to create a new Analytics account on your behalf.', 'google-site-kit' ), ), ), - 'GET:google-tag-settings' => array( - 'service' => 'tagmanager', - 'scopes' => array( - 'https://www.googleapis.com/auth/tagmanager.readonly', - ), + 'GET:google-tag-settings' => new Get_Google_Tag_Settings( + array( + 'service' => function () { + return $this->get_service( 'tagmanager' ); + }, + 'scopes' => array( + 'https://www.googleapis.com/auth/tagmanager.readonly', + ), + ) ), 'POST:create-property' => new Create_Property( array( @@ -832,11 +839,16 @@ protected function get_datapoint_definitions() { 'custom_dimensions_data_available' => $this->custom_dimensions_data_available, ) ), - 'POST:set-google-tag-id-mismatch' => array( - 'service' => '', + 'POST:set-google-tag-id-mismatch' => new Set_Google_Tag_ID_Mismatch( + array( + 'transients' => $this->transients, + ) ), - 'POST:set-is-web-data-stream-unavailable' => array( - 'service' => '', + 'POST:set-is-web-data-stream-unavailable' => new Set_Is_Web_Data_Stream_Unavailable( + array( + 'transients' => $this->transients, + 'settings' => $this->get_settings(), + ) ), 'POST:create-audience' => new Create_Audience( array( @@ -848,8 +860,10 @@ protected function get_datapoint_definitions() { 'request_scopes_message' => __( 'You’ll need to grant Site Kit permission to create new audiences for your Analytics property on your behalf.', 'google-site-kit' ), ) ), - 'POST:save-resource-data-availability-date' => array( - 'service' => '', + 'POST:save-resource-data-availability-date' => new Save_Resource_Data_Availability_Date( + array( + 'resource_data_availability_date' => $this->resource_data_availability_date, + ) ), 'POST:sync-audiences' => new Sync_Audiences( array( @@ -1385,45 +1399,6 @@ protected function create_data_request( Data_Request $data ) { $property_id, $batch_request ); - case 'POST:save-resource-data-availability-date': - if ( ! isset( $data['resourceType'] ) ) { - throw new Missing_Required_Param_Exception( 'resourceType' ); - } - - if ( ! isset( $data['resourceSlug'] ) ) { - throw new Missing_Required_Param_Exception( 'resourceSlug' ); - } - - if ( ! isset( $data['date'] ) ) { - throw new Missing_Required_Param_Exception( 'date' ); - } - - if ( ! $this->resource_data_availability_date->is_valid_resource_type( $data['resourceType'] ) ) { - throw new Invalid_Param_Exception( 'resourceType' ); - } - - if ( ! $this->resource_data_availability_date->is_valid_resource_slug( $data['resourceSlug'], $data['resourceType'] ) ) { - throw new Invalid_Param_Exception( 'resourceSlug' ); - } - - if ( ! is_int( $data['date'] ) ) { - throw new Invalid_Param_Exception( 'date' ); - } - - return function () use ( $data ) { - return $this->resource_data_availability_date->set_resource_date( $data['resourceSlug'], $data['resourceType'], $data['date'] ); - }; - case 'GET:google-tag-settings': - if ( ! isset( $data['measurementID'] ) ) { - return new WP_Error( - 'missing_required_param', - /* translators: %s: Missing parameter name */ - sprintf( __( 'Request parameter is empty: %s.', 'google-site-kit' ), 'measurementID' ), - array( 'status' => 400 ) - ); - } - - return $this->get_tagmanager_service()->accounts_containers->lookup( array( 'destinationId' => $data['measurementID'] ) ); case 'GET:key-events': $settings = $this->get_settings()->get(); if ( empty( $settings['propertyID'] ) ) { @@ -1440,42 +1415,6 @@ protected function create_data_request( Data_Request $data ) { return $analyticsadmin ->properties_keyEvents // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase ->listPropertiesKeyEvents( $property_id ); - case 'POST:set-google-tag-id-mismatch': - if ( ! isset( $data['hasMismatchedTag'] ) ) { - throw new Missing_Required_Param_Exception( 'hasMismatchedTag' ); - } - - if ( false === $data['hasMismatchedTag'] ) { - return function () { - $this->transients->delete( 'googlesitekit_inline_tag_id_mismatch' ); - return false; - }; - } - - return function () use ( $data ) { - $this->transients->set( 'googlesitekit_inline_tag_id_mismatch', $data['hasMismatchedTag'] ); - return $data['hasMismatchedTag']; - }; - case 'POST:set-is-web-data-stream-unavailable': - if ( ! isset( $data['isWebDataStreamUnavailable'] ) ) { - throw new Missing_Required_Param_Exception( 'isWebDataStreamUnavailable' ); - } - - if ( true === $data['isWebDataStreamUnavailable'] ) { - return function () { - $settings = $this->get_settings()->get(); - $transient_key = 'googlesitekit_web_data_stream_unavailable_' . $settings['webDataStreamID']; - $this->transients->set( $transient_key, true ); - return true; - }; - } - - return function () { - $settings = $this->get_settings()->get(); - $transient_key = 'googlesitekit_web_data_stream_unavailable_' . $settings['webDataStreamID']; - $this->transients->delete( $transient_key ); - return false; - }; } return parent::create_data_request( $data ); @@ -1502,8 +1441,6 @@ protected function parse_data_response( Data_Request $data, $response ) { ); case 'GET:property': return self::filter_property_with_ids( $response ); - case 'GET:google-tag-settings': - return $this->get_google_tag_settings_for_measurement_id( $response, $data['measurementID'] ); case 'GET:key-events': return (array) $response->getKeyEvents(); case 'GET:report': @@ -1937,61 +1874,6 @@ public function has_property_access( $property_id ) { return true; } - /** - * Gets the Google Tag Settings for the given measurement ID. - * - * @since 1.94.0 - * - * @param Google_Service_TagManager_Container $container Tag Manager container. - * @param string $measurement_id Measurement ID. - * @return array Google Tag Settings. - */ - protected function get_google_tag_settings_for_measurement_id( $container, $measurement_id ) { - return array( - 'googleTagAccountID' => $container->getAccountId(), - 'googleTagContainerID' => $container->getContainerId(), - 'googleTagID' => $this->determine_google_tag_id_from_tag_ids( $container->getTagIds(), $measurement_id ), - ); - } - - /** - * Determines Google Tag ID from the given Tag IDs. - * - * @since 1.94.0 - * - * @param array $tag_ids Tag IDs. - * @param string $measurement_id Measurement ID. - * @return string Google Tag ID. - */ - private function determine_google_tag_id_from_tag_ids( $tag_ids, $measurement_id ) { - // If there is only one tag id in the array, return it. - if ( count( $tag_ids ) === 1 ) { - return $tag_ids[0]; - } - - // If there are multiple tags, return the first one that starts with `GT-`. - foreach ( $tag_ids as $tag_id ) { - if ( substr( $tag_id, 0, 3 ) === 'GT-' ) { // strlen( 'GT-' ) === 3. - return $tag_id; - } - } - - // Otherwise, return the `$measurement_id` if it is in the array. - if ( in_array( $measurement_id, $tag_ids, true ) ) { - return $measurement_id; - } - - // Otherwise, return the first one that starts with `G-`. - foreach ( $tag_ids as $tag_id ) { - if ( substr( $tag_id, 0, 2 ) === 'G-' ) { // strlen( 'G-' ) === 2. - return $tag_id; - } - } - - // If none of the above, return the first one. - return $tag_ids[0]; - } - /** * Gets the Google Analytics 4 tag ID. * diff --git a/includes/Modules/Analytics_4/Datapoints/Get_Google_Tag_Settings.php b/includes/Modules/Analytics_4/Datapoints/Get_Google_Tag_Settings.php new file mode 100644 index 00000000000..191bd122a1e --- /dev/null +++ b/includes/Modules/Analytics_4/Datapoints/Get_Google_Tag_Settings.php @@ -0,0 +1,104 @@ + 400 ) + ); + } + + return $this->get_service() + ->accounts_containers + ->lookup( array( 'destinationId' => $data_request['measurementID'] ) ); + } + + /** + * Parses a response. + * + * @since n.e.x.t + * + * @param mixed $response Request response. + * @param Data_Request $data Data request object. + * @return array Parsed Google Tag settings. + */ + public function parse_response( $response, Data_Request $data ) { + return array( + 'googleTagAccountID' => $response->getAccountId(), + 'googleTagContainerID' => $response->getContainerId(), + 'googleTagID' => $this->determine_google_tag_id_from_tag_ids( $response->getTagIds(), $data['measurementID'] ), + ); + } + + /** + * Determines Google Tag ID from the given Tag IDs. + * + * @since n.e.x.t + * + * @param array $tag_ids Tag IDs. + * @param string $measurement_id Measurement ID. + * @return string Google Tag ID. + */ + private function determine_google_tag_id_from_tag_ids( $tag_ids, $measurement_id ) { + // If there is only one tag id in the array, return it. + if ( count( $tag_ids ) === 1 ) { + return $tag_ids[0]; + } + + // If there are multiple tags, return the first one that starts with `GT-`. + foreach ( $tag_ids as $tag_id ) { + if ( substr( $tag_id, 0, 3 ) === 'GT-' ) { // strlen( 'GT-' ) === 3. + return $tag_id; + } + } + + // Otherwise, return the `$measurement_id` if it is in the array. + if ( in_array( $measurement_id, $tag_ids, true ) ) { + return $measurement_id; + } + + // Otherwise, return the first one that starts with `G-`. + foreach ( $tag_ids as $tag_id ) { + if ( substr( $tag_id, 0, 2 ) === 'G-' ) { // strlen( 'G-' ) === 2. + return $tag_id; + } + } + + // If none of the above, return the first one. + return $tag_ids[0]; + } +} diff --git a/includes/Modules/Analytics_4/Datapoints/Save_Resource_Data_Availability_Date.php b/includes/Modules/Analytics_4/Datapoints/Save_Resource_Data_Availability_Date.php new file mode 100644 index 00000000000..f87265817ee --- /dev/null +++ b/includes/Modules/Analytics_4/Datapoints/Save_Resource_Data_Availability_Date.php @@ -0,0 +1,101 @@ +resource_data_availability_date = $definition['resource_data_availability_date']; + } + + /** + * Creates a request object. + * + * @since n.e.x.t + * + * @param Data_Request $data_request Data request object. + * @return callable Closure that saves the resource data availability date. + * @throws Missing_Required_Param_Exception Thrown if a required parameter is missing. + * @throws Invalid_Param_Exception Thrown if a parameter is invalid. + */ + public function create_request( Data_Request $data_request ) { + if ( ! isset( $data_request['resourceType'] ) ) { + throw new Missing_Required_Param_Exception( 'resourceType' ); + } + + if ( ! isset( $data_request['resourceSlug'] ) ) { + throw new Missing_Required_Param_Exception( 'resourceSlug' ); + } + + if ( ! isset( $data_request['date'] ) ) { + throw new Missing_Required_Param_Exception( 'date' ); + } + + if ( ! $this->resource_data_availability_date->is_valid_resource_type( $data_request['resourceType'] ) ) { + throw new Invalid_Param_Exception( 'resourceType' ); + } + + if ( ! $this->resource_data_availability_date->is_valid_resource_slug( $data_request['resourceSlug'], $data_request['resourceType'] ) ) { + throw new Invalid_Param_Exception( 'resourceSlug' ); + } + + if ( ! is_int( $data_request['date'] ) ) { + throw new Invalid_Param_Exception( 'date' ); + } + + return function () use ( $data_request ) { + return $this->resource_data_availability_date->set_resource_date( $data_request['resourceSlug'], $data_request['resourceType'], $data_request['date'] ); + }; + } + + /** + * Parses a response. + * + * @since n.e.x.t + * + * @param mixed $response Request response. + * @param Data_Request $data Data request object. + * @return mixed The response without any modifications. + */ + public function parse_response( $response, Data_Request $data ) { + return $response; + } +} diff --git a/includes/Modules/Analytics_4/Datapoints/Set_Google_Tag_ID_Mismatch.php b/includes/Modules/Analytics_4/Datapoints/Set_Google_Tag_ID_Mismatch.php new file mode 100644 index 00000000000..a3e9ed20b5e --- /dev/null +++ b/includes/Modules/Analytics_4/Datapoints/Set_Google_Tag_ID_Mismatch.php @@ -0,0 +1,87 @@ +transients = $definition['transients']; + } + + /** + * Creates a request object. + * + * @since n.e.x.t + * + * @param Data_Request $data_request Data request object. + * @return callable Closure that sets or deletes the tag ID mismatch transient. + * @throws Missing_Required_Param_Exception Thrown if a required parameter is missing. + */ + public function create_request( Data_Request $data_request ) { + if ( ! isset( $data_request['hasMismatchedTag'] ) ) { + throw new Missing_Required_Param_Exception( 'hasMismatchedTag' ); + } + + if ( false === $data_request['hasMismatchedTag'] ) { + return function () { + $this->transients->delete( 'googlesitekit_inline_tag_id_mismatch' ); + return false; + }; + } + + return function () use ( $data_request ) { + $this->transients->set( 'googlesitekit_inline_tag_id_mismatch', $data_request['hasMismatchedTag'] ); + return $data_request['hasMismatchedTag']; + }; + } + + /** + * Parses a response. + * + * @since n.e.x.t + * + * @param mixed $response Request response. + * @param Data_Request $data Data request object. + * @return mixed The response without any modifications. + */ + public function parse_response( $response, Data_Request $data ) { + return $response; + } +} diff --git a/includes/Modules/Analytics_4/Datapoints/Set_Is_Web_Data_Stream_Unavailable.php b/includes/Modules/Analytics_4/Datapoints/Set_Is_Web_Data_Stream_Unavailable.php new file mode 100644 index 00000000000..3d4c52776b0 --- /dev/null +++ b/includes/Modules/Analytics_4/Datapoints/Set_Is_Web_Data_Stream_Unavailable.php @@ -0,0 +1,101 @@ +transients = $definition['transients']; + $this->settings = $definition['settings']; + } + + /** + * Creates a request object. + * + * @since n.e.x.t + * + * @param Data_Request $data_request Data request object. + * @return callable Closure that sets or deletes the web data stream unavailable transient. + * @throws Missing_Required_Param_Exception Thrown if a required parameter is missing. + */ + public function create_request( Data_Request $data_request ) { + if ( ! isset( $data_request['isWebDataStreamUnavailable'] ) ) { + throw new Missing_Required_Param_Exception( 'isWebDataStreamUnavailable' ); + } + + if ( true === $data_request['isWebDataStreamUnavailable'] ) { + return function () { + $settings = $this->settings->get(); + $transient_key = 'googlesitekit_web_data_stream_unavailable_' . $settings['webDataStreamID']; + $this->transients->set( $transient_key, true ); + return true; + }; + } + + return function () { + $settings = $this->settings->get(); + $transient_key = 'googlesitekit_web_data_stream_unavailable_' . $settings['webDataStreamID']; + $this->transients->delete( $transient_key ); + return false; + }; + } + + /** + * Parses a response. + * + * @since n.e.x.t + * + * @param mixed $response Request response. + * @param Data_Request $data Data request object. + * @return mixed The response without any modifications. + */ + public function parse_response( $response, Data_Request $data ) { + return $response; + } +} diff --git a/tests/phpunit/integration/Modules/Analytics_4/Datapoints/Get_Google_Tag_SettingsTest.php b/tests/phpunit/integration/Modules/Analytics_4/Datapoints/Get_Google_Tag_SettingsTest.php new file mode 100644 index 00000000000..91a99fe9d46 --- /dev/null +++ b/tests/phpunit/integration/Modules/Analytics_4/Datapoints/Get_Google_Tag_SettingsTest.php @@ -0,0 +1,210 @@ +factory()->user->create_and_get( array( 'role' => 'administrator' ) ); + $user_options = new User_Options( $context, $user->ID ); + $authentication = new Authentication( $context, $options, $user_options ); + $this->analytics = new Analytics_4( $context, $options, $user_options, $authentication ); + + $this->analytics->get_client()->withDefer( true ); + $service = new Google_Service_TagManager( $this->analytics->get_client() ); + + $this->datapoint = new Get_Google_Tag_Settings( + array( + 'service' => function () use ( $service ) { + return $service; + }, + 'scopes' => array( 'https://www.googleapis.com/auth/tagmanager.readonly' ), + ) + ); + + FakeHttp::fake_google_http_handler( + $this->analytics->get_client(), + function ( Request $request ) { + $this->tag_settings_request = $request; + + $container = new Container(); + $container->setAccountId( '12345' ); + $container->setContainerId( '67890' ); + $container->setTagIds( array( 'GT-ABCDEFG' ) ); + + return new FulfilledPromise( new Response( 200, array(), wp_json_encode( $container ) ) ); + } + ); + } + + public function test_create_request__requires_measurement_id() { + $data_request = new Data_Request( 'GET', 'modules', 'analytics-4', 'google-tag-settings', array() ); + $response = $this->datapoint->create_request( $data_request ); + + $this->assertInstanceOf( WP_Error::class, $response, 'Missing measurementID should return a WP_Error response.' ); + $this->assertEquals( 'missing_required_param', $response->get_error_code(), 'Missing measurementID should return missing_required_param.' ); + } + + public function test_create_request() { + $this->tag_settings_request = null; + + $data_request = new Data_Request( + 'GET', + 'modules', + 'analytics-4', + 'google-tag-settings', + array( + 'measurementID' => 'G-12345', + ) + ); + + $request = $this->datapoint->create_request( $data_request ); + $this->analytics->get_client()->execute( $request ); + + $this->assertEquals( + 'https://tagmanager.googleapis.com/tagmanager/v2/accounts/containers:lookup?destinationId=G-12345', + (string) $this->tag_settings_request->getUri(), + 'The request should be made to the correct GTM container lookup endpoint.' + ); + } + + public function test_parse_response() { + $container = new Container(); + $container->setAccountId( '12345' ); + $container->setContainerId( '67890' ); + $container->setTagIds( array( 'GT-ABCDEFG' ) ); + + $data_request = new Data_Request( + 'GET', + 'modules', + 'analytics-4', + 'google-tag-settings', + array( + 'measurementID' => 'G-12345', + ) + ); + + $response = $this->datapoint->parse_response( $container, $data_request ); + + $this->assertEquals( '12345', $response['googleTagAccountID'], 'The response should include the googleTagAccountID.' ); + $this->assertEquals( '67890', $response['googleTagContainerID'], 'The response should include the googleTagContainerID.' ); + $this->assertEquals( 'GT-ABCDEFG', $response['googleTagID'], 'The response should include the googleTagID.' ); + } + + public function test_parse_response__single_tag_id_returned() { + $container = new Container(); + $container->setAccountId( '12345' ); + $container->setContainerId( '67890' ); + $container->setTagIds( array( 'G-ONLYONE' ) ); + + $data_request = new Data_Request( + 'GET', + 'modules', + 'analytics-4', + 'google-tag-settings', + array( + 'measurementID' => 'G-ONLYONE', + ) + ); + + $response = $this->datapoint->parse_response( $container, $data_request ); + + $this->assertEquals( 'G-ONLYONE', $response['googleTagID'], 'When there is only one tag ID, it should be returned.' ); + } + + public function test_parse_response__prefers_gt_prefix_over_g_prefix() { + $container = new Container(); + $container->setAccountId( '12345' ); + $container->setContainerId( '67890' ); + $container->setTagIds( array( 'G-FIRST', 'GT-SECOND' ) ); + + $data_request = new Data_Request( + 'GET', + 'modules', + 'analytics-4', + 'google-tag-settings', + array( + 'measurementID' => 'G-FIRST', + ) + ); + + $response = $this->datapoint->parse_response( $container, $data_request ); + + $this->assertEquals( 'GT-SECOND', $response['googleTagID'], 'When multiple tag IDs exist, a GT- prefixed tag should be preferred.' ); + } + + public function test_parse_response__falls_back_to_measurement_id_match() { + $container = new Container(); + $container->setAccountId( '12345' ); + $container->setContainerId( '67890' ); + $container->setTagIds( array( 'G-OTHER1', 'G-MEASURED' ) ); + + $data_request = new Data_Request( + 'GET', + 'modules', + 'analytics-4', + 'google-tag-settings', + array( + 'measurementID' => 'G-MEASURED', + ) + ); + + $response = $this->datapoint->parse_response( $container, $data_request ); + + $this->assertEquals( 'G-MEASURED', $response['googleTagID'], 'When no GT- tag exists but measurementID is in the list, it should be returned.' ); + } +} diff --git a/tests/phpunit/integration/Modules/Analytics_4/Datapoints/Save_Resource_Data_Availability_DateTest.php b/tests/phpunit/integration/Modules/Analytics_4/Datapoints/Save_Resource_Data_Availability_DateTest.php new file mode 100644 index 00000000000..ef511682022 --- /dev/null +++ b/tests/phpunit/integration/Modules/Analytics_4/Datapoints/Save_Resource_Data_Availability_DateTest.php @@ -0,0 +1,190 @@ +factory()->user->create_and_get( array( 'role' => 'administrator' ) ); + $user_options = new User_Options( $context, $user->ID ); + $authentication = new Authentication( $context, $options, $user_options ); + $this->analytics = new Analytics_4( $context, $options, $user_options, $authentication ); + + $transients = new Transients( $context ); + $audience_settings = new Audience_Settings( $options ); + $this->resource_data_availability_date = new Resource_Data_Availability_Date( + $transients, + $this->analytics->get_settings(), + $audience_settings + ); + + $this->datapoint = new Save_Resource_Data_Availability_Date( + array( + 'resource_data_availability_date' => $this->resource_data_availability_date, + 'service' => '', + ) + ); + } + + public function required_params() { + return array( + array( 'resourceType' ), + array( 'resourceSlug' ), + array( 'date' ), + ); + } + + /** + * @dataProvider required_params + */ + public function test_create_request__requires_params( $required_param ) { + $data = array( + 'resourceType' => Resource_Data_Availability_Date::RESOURCE_TYPE_CUSTOM_DIMENSION, + 'resourceSlug' => 'googlesitekit_post_type', + 'date' => 20201231, + ); + unset( $data[ $required_param ] ); + + $data_request = new Data_Request( 'POST', 'modules', 'analytics-4', 'save-resource-data-availability-date', $data ); + + $this->expectException( Missing_Required_Param_Exception::class ); + $this->datapoint->create_request( $data_request ); + } + + public function test_create_request__validates_resource_type() { + $data_request = new Data_Request( + 'POST', + 'modules', + 'analytics-4', + 'save-resource-data-availability-date', + array( + 'resourceType' => 'invalid-resource-type', + 'resourceSlug' => 'googlesitekit_post_type', + 'date' => 20201231, + ) + ); + + $this->expectException( Invalid_Param_Exception::class ); + $this->expectExceptionMessage( 'Invalid parameter: resourceType.' ); + $this->datapoint->create_request( $data_request ); + } + + public function test_create_request__validates_resource_slug() { + $data_request = new Data_Request( + 'POST', + 'modules', + 'analytics-4', + 'save-resource-data-availability-date', + array( + 'resourceType' => Resource_Data_Availability_Date::RESOURCE_TYPE_CUSTOM_DIMENSION, + 'resourceSlug' => 'invalid-slug', + 'date' => 20201231, + ) + ); + + $this->expectException( Invalid_Param_Exception::class ); + $this->expectExceptionMessage( 'Invalid parameter: resourceSlug.' ); + $this->datapoint->create_request( $data_request ); + } + + public function test_create_request__validates_date_type() { + $data_request = new Data_Request( + 'POST', + 'modules', + 'analytics-4', + 'save-resource-data-availability-date', + array( + 'resourceType' => Resource_Data_Availability_Date::RESOURCE_TYPE_CUSTOM_DIMENSION, + 'resourceSlug' => 'googlesitekit_post_type', + 'date' => '20201231', + ) + ); + + $this->expectException( Invalid_Param_Exception::class ); + $this->expectExceptionMessage( 'Invalid parameter: date.' ); + $this->datapoint->create_request( $data_request ); + } + + public function test_create_request() { + $data_request = new Data_Request( + 'POST', + 'modules', + 'analytics-4', + 'save-resource-data-availability-date', + array( + 'resourceType' => Resource_Data_Availability_Date::RESOURCE_TYPE_CUSTOM_DIMENSION, + 'resourceSlug' => 'googlesitekit_post_type', + 'date' => 20201231, + ) + ); + + $request = $this->datapoint->create_request( $data_request ); + $response = $request(); + + $this->assertTrue( $response, 'The datapoint should return true on success.' ); + $this->assertEquals( + 20201231, + $this->resource_data_availability_date->get_resource_date( 'googlesitekit_post_type', Resource_Data_Availability_Date::RESOURCE_TYPE_CUSTOM_DIMENSION ), + 'The resource data availability date should be saved.' + ); + } + + public function test_parse_response() { + $data_request = new Data_Request( 'POST', 'modules', 'analytics-4', 'save-resource-data-availability-date', array() ); + + $this->assertTrue( $this->datapoint->parse_response( true, $data_request ), 'The `parse_response` method should return the response unchanged.' ); + $this->assertFalse( $this->datapoint->parse_response( false, $data_request ), 'The `parse_response` method should return the response unchanged.' ); + } +} diff --git a/tests/phpunit/integration/Modules/Analytics_4/Datapoints/Set_Google_Tag_ID_MismatchTest.php b/tests/phpunit/integration/Modules/Analytics_4/Datapoints/Set_Google_Tag_ID_MismatchTest.php new file mode 100644 index 00000000000..db9fe0c08b1 --- /dev/null +++ b/tests/phpunit/integration/Modules/Analytics_4/Datapoints/Set_Google_Tag_ID_MismatchTest.php @@ -0,0 +1,113 @@ +transients = new Transients( $context ); + $this->datapoint = new Set_Google_Tag_ID_Mismatch( + array( + 'transients' => $this->transients, + 'service' => '', + ) + ); + } + + public function test_create_request__requires_has_mismatched_tag() { + $data_request = new Data_Request( + 'POST', + 'modules', + 'analytics-4', + 'set-google-tag-id-mismatch', + array() + ); + + $this->expectException( Missing_Required_Param_Exception::class ); + $this->expectExceptionMessage( 'Request parameter is empty: hasMismatchedTag.' ); + $this->datapoint->create_request( $data_request ); + } + + public function test_create_request__sets_transient_when_mismatched() { + $data_request = new Data_Request( + 'POST', + 'modules', + 'analytics-4', + 'set-google-tag-id-mismatch', + array( + 'hasMismatchedTag' => 'GT-MISMATCH', + ) + ); + + $request = $this->datapoint->create_request( $data_request ); + $response = $request(); + + $this->assertEquals( 'GT-MISMATCH', $response, 'The datapoint should return the hasMismatchedTag value.' ); + $this->assertEquals( 'GT-MISMATCH', $this->transients->get( 'googlesitekit_inline_tag_id_mismatch' ), 'The transient should be set with the hasMismatchedTag value.' ); + } + + public function test_create_request__deletes_transient_when_not_mismatched() { + // First set the transient. + $this->transients->set( 'googlesitekit_inline_tag_id_mismatch', 'GT-MISMATCH' ); + + $data_request = new Data_Request( + 'POST', + 'modules', + 'analytics-4', + 'set-google-tag-id-mismatch', + array( + 'hasMismatchedTag' => false, + ) + ); + + $request = $this->datapoint->create_request( $data_request ); + $response = $request(); + + $this->assertFalse( $response, 'The datapoint should return false when hasMismatchedTag is false.' ); + $this->assertFalse( $this->transients->get( 'googlesitekit_inline_tag_id_mismatch' ), 'The transient should be deleted when hasMismatchedTag is false.' ); + } + + public function test_parse_response() { + $data_request = new Data_Request( 'POST', 'modules', 'analytics-4', 'set-google-tag-id-mismatch', array() ); + $test_data = 'GT-ABCD'; + + $this->assertSame( $test_data, $this->datapoint->parse_response( $test_data, $data_request ), 'The `parse_response` method should return the response unchanged.' ); + } +} diff --git a/tests/phpunit/integration/Modules/Analytics_4/Datapoints/Set_Is_Web_Data_Stream_UnavailableTest.php b/tests/phpunit/integration/Modules/Analytics_4/Datapoints/Set_Is_Web_Data_Stream_UnavailableTest.php new file mode 100644 index 00000000000..37c4d29572d --- /dev/null +++ b/tests/phpunit/integration/Modules/Analytics_4/Datapoints/Set_Is_Web_Data_Stream_UnavailableTest.php @@ -0,0 +1,147 @@ +factory()->user->create_and_get( array( 'role' => 'administrator' ) ); + $user_options = new User_Options( $context, $user->ID ); + $authentication = new Authentication( $context, $options, $user_options ); + $this->analytics = new Analytics_4( $context, $options, $user_options, $authentication ); + $this->transients = new Transients( $context ); + + $this->datapoint = new Set_Is_Web_Data_Stream_Unavailable( + array( + 'transients' => $this->transients, + 'settings' => $this->analytics->get_settings(), + 'service' => '', + ) + ); + } + + public function test_create_request__requires_is_web_data_stream_unavailable() { + $data_request = new Data_Request( + 'POST', + 'modules', + 'analytics-4', + 'set-is-web-data-stream-unavailable', + array() + ); + + $this->expectException( Missing_Required_Param_Exception::class ); + $this->expectExceptionMessage( 'Request parameter is empty: isWebDataStreamUnavailable.' ); + $this->datapoint->create_request( $data_request ); + } + + public function test_create_request__sets_transient_when_unavailable() { + $web_data_stream_id = '654321'; + $this->analytics->get_settings()->merge( + array( + 'webDataStreamID' => $web_data_stream_id, + ) + ); + + $data_request = new Data_Request( + 'POST', + 'modules', + 'analytics-4', + 'set-is-web-data-stream-unavailable', + array( + 'isWebDataStreamUnavailable' => true, + ) + ); + + $request = $this->datapoint->create_request( $data_request ); + $response = $request(); + + $this->assertTrue( $response, 'The datapoint should return true when isWebDataStreamUnavailable is true.' ); + $transient_key = 'googlesitekit_web_data_stream_unavailable_' . $web_data_stream_id; + $this->assertTrue( $this->transients->get( $transient_key ), 'The transient should be set when isWebDataStreamUnavailable is true.' ); + } + + public function test_create_request__deletes_transient_when_available() { + $web_data_stream_id = '654321'; + $this->analytics->get_settings()->merge( + array( + 'webDataStreamID' => $web_data_stream_id, + ) + ); + + $transient_key = 'googlesitekit_web_data_stream_unavailable_' . $web_data_stream_id; + // First set the transient. + $this->transients->set( $transient_key, true ); + + $data_request = new Data_Request( + 'POST', + 'modules', + 'analytics-4', + 'set-is-web-data-stream-unavailable', + array( + 'isWebDataStreamUnavailable' => false, + ) + ); + + $request = $this->datapoint->create_request( $data_request ); + $response = $request(); + + $this->assertFalse( $response, 'The datapoint should return false when isWebDataStreamUnavailable is false.' ); + $this->assertFalse( $this->transients->get( $transient_key ), 'The transient should be deleted when isWebDataStreamUnavailable is false.' ); + } + + public function test_parse_response() { + $data_request = new Data_Request( 'POST', 'modules', 'analytics-4', 'set-is-web-data-stream-unavailable', array() ); + + $this->assertTrue( $this->datapoint->parse_response( true, $data_request ), 'The `parse_response` method should return the response unchanged.' ); + $this->assertFalse( $this->datapoint->parse_response( false, $data_request ), 'The `parse_response` method should return the response unchanged.' ); + } +}