diff --git a/changelog.txt b/changelog.txt index f1b6eb24e..17300debe 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ = 1.25.6 - 202x-xx-xx = * Fix - Refreshes shipping methods after registering or removing carrier accounts. +* Add - Remember state of "Mark this order as complete and notify the customer" and "Notify the customer with shipment details" checkboxes. = 1.25.5 - 2021-01-11 = * Fix - Redux DevTools usage update. diff --git a/classes/class-wc-connect-options.php b/classes/class-wc-connect-options.php index 04d1b3b0d..cf032f501 100644 --- a/classes/class-wc-connect-options.php +++ b/classes/class-wc-connect-options.php @@ -43,6 +43,7 @@ public static function get_option_names( $type = 'compact' ) { 'payment_methods', 'account_settings', 'paper_size', + 'post_print_notification_settings', 'packages', 'predefined_packages', 'shipping_methods_migrated', diff --git a/classes/class-wc-connect-service-settings-store.php b/classes/class-wc-connect-service-settings-store.php index 8fb99b963..7a157a0e0 100644 --- a/classes/class-wc-connect-service-settings-store.php +++ b/classes/class-wc-connect-service-settings-store.php @@ -160,6 +160,67 @@ public function set_preferred_paper_size( $size ) { return WC_Connect_Options::update_option( 'paper_size', $size ); } + /** + * Gets post-label-printing notification settings. + * + * @return array Array of boolean values, indexed by setting names. + */ + public function get_post_print_notification_settings() { + $defaults = array( + 'mark_order_complete_and_notify_customer' => false, + 'notify_customer_with_shipment_details' => false, + ); + + $settings = WC_Connect_Options::get_option( 'post_print_notification_settings', $defaults ); + + return array_merge( $defaults, $settings ); + } + + /** + * Updates post-label-printing notification settings. + * + * @param string $name Name of the setting to enable/disable. + * @param bool $enabled Whether the setting should be enabled. + * + * @return true|WP_Error WP_Error if an error occurred, `true` otherwise. + */ + public function set_post_print_notification_setting( $name, $enabled ) { + $allowed_names = array( + 'mark_order_complete_and_notify_customer', + 'notify_customer_with_shipment_details', + ); + + if ( ! in_array( $name, $allowed_names, true ) ) { + return new WP_Error( + 'invalid_notification_setting_name', + __( 'Invalid notification setting name supplied.', 'woocommerce-services' ) + ); + } + + $old_settings = WC_Connect_Options::get_option( 'post_print_notification_settings' ); + $settings = $old_settings; + $settings[ $name ] = (bool) $enabled; + + /* + * WC_Connect_Options::update_option() returns `false` if the new value is the same as the old one. + * As this is not an issue in this case, we return `true` here and leave the option unchanged. + */ + if ( $settings === $old_settings ) { + return true; + } + + $result = WC_Connect_Options::update_option( 'post_print_notification_settings', $settings ); + + if ( ! $result ) { + return new WP_Error( + 'save_failed', + __( 'Updating the option failed.', 'woocommerce-services' ) + ); + } + + return $result; + } + /** * Attempts to recover faulty json string fields that might contain strings with unescaped quotes * diff --git a/classes/class-wc-connect-shipping-label.php b/classes/class-wc-connect-shipping-label.php index 4d5629a0a..f086c5943 100644 --- a/classes/class-wc-connect-shipping-label.php +++ b/classes/class-wc-connect-shipping-label.php @@ -391,10 +391,14 @@ public function get_label_payload( $post_order_or_id ) { return false; } + $notification_settings = $this->settings_store->get_post_print_notification_settings(); + $order_id = WC_Connect_Compatibility::instance()->get_order_id( $order ); $payload = array( 'orderId' => $order_id, 'paperSize' => $this->settings_store->get_preferred_paper_size(), + 'fulfillOrder' => $notification_settings['mark_order_complete_and_notify_customer'], + 'emailDetails' => $notification_settings['notify_customer_with_shipment_details'], 'formData' => $this->get_form_data( $order ), 'labelsData' => $this->settings_store->get_label_order_meta_data( $order_id ), 'storeOptions' => $this->settings_store->get_store_options(), diff --git a/classes/class-wc-rest-connect-post-print-notification-settings-controller.php b/classes/class-wc-rest-connect-post-print-notification-settings-controller.php new file mode 100644 index 000000000..2389afeed --- /dev/null +++ b/classes/class-wc-rest-connect-post-print-notification-settings-controller.php @@ -0,0 +1,34 @@ +settings_store->set_post_print_notification_setting( $request['name'], $request['enabled'] ); + + if ( is_wp_error( $result ) ) { + $error = new WP_Error( + 'save_failed', + sprintf( + __( 'Unable to update notification setting. %s', 'woocommerce-services' ), + $result->get_error_message() + ), + array( 'status' => 400 ) + ); + + $this->logger->log( $error, __CLASS__ ); + + return $error; + } + + return new WP_REST_Response( array( 'success' => true ), 200 ); + } +} diff --git a/client/extensions/woocommerce/woocommerce-services/api/url.js b/client/extensions/woocommerce/woocommerce-services/api/url.js index 33b4e9df5..60bbd9bae 100644 --- a/client/extensions/woocommerce/woocommerce-services/api/url.js +++ b/client/extensions/woocommerce/woocommerce-services/api/url.js @@ -1,5 +1,6 @@ /** @format */ export const accountSettings = 'connect/account/settings'; +export const postPrintNotificationSettings = 'connect/post-print-notification-settings'; export const packages = 'connect/packages'; export const orderLabels = ( orderId ) => `connect/label/${ orderId }`; export const getLabelRates = ( orderId ) => `connect/label/${ orderId }/rates`; diff --git a/client/extensions/woocommerce/woocommerce-services/lib/initialize-labels-state/index.js b/client/extensions/woocommerce/woocommerce-services/lib/initialize-labels-state/index.js index eb2ecaaf4..701c77227 100644 --- a/client/extensions/woocommerce/woocommerce-services/lib/initialize-labels-state/index.js +++ b/client/extensions/woocommerce/woocommerce-services/lib/initialize-labels-state/index.js @@ -31,12 +31,10 @@ export default data => { loaded: false, isFetching: false, error: false, - fulfillOrder: false, - emailDetails: false, }; } - const { formData, labelsData, paperSize, storeOptions, canChangeCountries } = data; + const { formData, labelsData, paperSize, fulfillOrder, emailDetails, storeOptions, canChangeCountries } = data; //old WCS required a phone number and detected normalization status based on the existence of the phone field //newer versions send the normalized flag const originNormalized = Boolean( formData.origin_normalized || formData.origin.phone ); @@ -74,8 +72,8 @@ export default data => { loaded: true, isFetching: false, error: false, - fulfillOrder: false, - emailDetails: false, + fulfillOrder, + emailDetails, refreshedLabelStatus: false, labels: labelsData || [], paperSize, diff --git a/client/extensions/woocommerce/woocommerce-services/state/shipping-label/actions.js b/client/extensions/woocommerce/woocommerce-services/state/shipping-label/actions.js index 24e855adb..36ab8a5cf 100644 --- a/client/extensions/woocommerce/woocommerce-services/state/shipping-label/actions.js +++ b/client/extensions/woocommerce/woocommerce-services/state/shipping-label/actions.js @@ -44,6 +44,8 @@ import { } from './selectors'; import { createNote } from 'woocommerce/state/sites/orders/notes/actions'; import { saveOrder } from 'woocommerce/state/sites/orders/actions'; +import { getOrder } from 'woocommerce/state/sites/orders/selectors'; +import { isOrderFinished } from 'woocommerce/lib/order-status'; import { getAllPackageDefinitions } from 'woocommerce/woocommerce-services/state/packages/selectors'; import { getEmailReceipts } from 'woocommerce/woocommerce-services/state/label-settings/selectors'; import getAddressValues from 'woocommerce/woocommerce-services/lib/utils/get-address-values'; @@ -729,6 +731,26 @@ export const setFulfillOrderOption = ( orderId, siteId, value ) => { }; }; +export const updatePostPrintNotificationSettings = ( state, orderId, siteId ) => { + const { fulfillOrder, emailDetails } = getShippingLabel( state, orderId, siteId ); + const order = getOrder( state, orderId ); + let data = {}; + + if ( isOrderFinished( order.status ) ) { + data = { + name: 'notify_customer_with_shipment_details', + enabled: emailDetails, + }; + } else { + data = { + name: 'mark_order_complete_and_notify_customer', + enabled: fulfillOrder, + }; + } + + api.post( siteId, api.url.postPrintNotificationSettings, data ); +}; + const purchaseLabelResponse = ( orderId, siteId, response, error ) => { return { type: WOOCOMMERCE_SERVICES_SHIPPING_LABEL_PURCHASE_RESPONSE, @@ -777,7 +799,7 @@ const labelStatusTask = ( orderId, siteId, labelId, retryCount ) => { } ); }; -const handlePrintFinished = ( orderId, siteId, dispatch, getState, hasError, labels ) => { +export const handlePrintFinished = ( orderId, siteId, dispatch, getState, hasError, labels ) => { dispatch( exitPrintingFlow( orderId, siteId, true ) ); dispatch( clearAvailableRates( orderId, siteId ) ); @@ -824,6 +846,8 @@ const handlePrintFinished = ( orderId, siteId, dispatch, getState, hasError, lab } ) ); } + + updatePostPrintNotificationSettings( getState(), orderId, siteId ); }; /** diff --git a/client/extensions/woocommerce/woocommerce-services/state/shipping-label/selectors.js b/client/extensions/woocommerce/woocommerce-services/state/shipping-label/selectors.js index b5bbe256d..6e4965c12 100644 --- a/client/extensions/woocommerce/woocommerce-services/state/shipping-label/selectors.js +++ b/client/extensions/woocommerce/woocommerce-services/state/shipping-label/selectors.js @@ -55,6 +55,8 @@ import { hasStates, } from 'woocommerce/state/sites/data/locations/selectors'; import { isWcsInternationalLabelsEnabled } from 'woocommerce/state/selectors/plugins'; +import { getOrder } from 'woocommerce/state/sites/orders/selectors'; +import { isOrderFinished } from '../../../lib/order-status'; export const getShippingLabel = ( state, orderId, siteId = getSelectedSiteId( state ) ) => { return get( @@ -92,12 +94,14 @@ export const getLabelById = ( state, orderId, siteId, labelId ) => { export const shouldFulfillOrder = ( state, orderId, siteId = getSelectedSiteId( state ) ) => { const shippingLabel = getShippingLabel( state, orderId, siteId ); - return shippingLabel && shippingLabel.fulfillOrder; + const order = getOrder( state, orderId ); + return shippingLabel && shippingLabel.fulfillOrder && order && ! isOrderFinished( order.status ); }; export const shouldEmailDetails = ( state, orderId, siteId = getSelectedSiteId( state ) ) => { const shippingLabel = getShippingLabel( state, orderId, siteId ); - return shippingLabel && shippingLabel.emailDetails; + const order = getOrder( state, orderId ); + return shippingLabel && shippingLabel.emailDetails && order && isOrderFinished( order.status ); }; export const getSelectedPaymentMethod = ( state, orderId, siteId = getSelectedSiteId( state ) ) => { diff --git a/client/extensions/woocommerce/woocommerce-services/state/shipping-label/test/actions.js b/client/extensions/woocommerce/woocommerce-services/state/shipping-label/test/actions.js index f2cdc449b..19cc0fb51 100644 --- a/client/extensions/woocommerce/woocommerce-services/state/shipping-label/test/actions.js +++ b/client/extensions/woocommerce/woocommerce-services/state/shipping-label/test/actions.js @@ -12,6 +12,7 @@ import nock from 'nock'; */ import { openPrintingFlow, + handlePrintFinished, convertToApiPackage, submitAddressForNormalization, confirmAddressSuggestion, @@ -269,6 +270,85 @@ describe( 'Shipping label Actions', () => { nock.cleanAll(); } ); + const createGetStateFnForPostPrintNotificationSettings = ( orderStatus, notificationSettings ) => () => ( { + ui: { + selectedSiteId: siteId, + }, + extensions: { + woocommerce: { + sites: { + [ siteId ]: { + orders: { + items: { + [ orderId ]: { + status: orderStatus, + }, + } + } + }, + }, + woocommerceServices: { + [ siteId ]: { + shippingLabel: { + [ orderId ]: notificationSettings, + }, + }, + }, + }, + }, + } ); + + const mockPostPrintNotificationSettingsUpdateRequest = expectedBody => { + return nock( 'https://public-api.wordpress.com:443' ) + .post( + `/rest/v1.1/jetpack-blogs/${ siteId }/rest-api/`, + body => { + const expectedPath = '/wc/v1/connect/post-print-notification-settings&_via_calypso&_method=post'; + + return expectedPath === body.path && JSON.stringify( expectedBody ) === body.body; + } + ) + .reply( 200, { success: true } ); + }; + + const testPostPrintNotificationSettingsUpdate = ( orderStatus, state, expectedBody ) => { + const getState = createGetStateFnForPostPrintNotificationSettings( orderStatus, state ); + const request = mockPostPrintNotificationSettingsUpdateRequest( expectedBody ); + handlePrintFinished( orderId, siteId, sinon.spy(), getState, false, [] ); + request.done(); + }; + + const testCases = [ + { + orderStatus: 'completed', + state: { name: 'emailDetails', value: true }, + expectedBody: { name: 'notify_customer_with_shipment_details', enabled: true }, + }, + { + orderStatus: 'completed', + state: { name: 'emailDetails', value: false }, + expectedBody: { name: 'notify_customer_with_shipment_details', enabled: false }, + }, + { + orderStatus: 'pending', + state: { name: 'fulfillOrder', value: true }, + expectedBody: { name: 'mark_order_complete_and_notify_customer', enabled: true }, + }, + { + orderStatus: 'pending', + state: { name: 'fulfillOrder', value: false }, + expectedBody: { name: 'mark_order_complete_and_notify_customer', enabled: false }, + }, + ]; + + describe.each( testCases )( '#handlePrintFinished', testCase => { + const { expectedBody, orderStatus, state } = testCase; + + it( `sets "${expectedBody.name}" to ${expectedBody.value}`, () => { + testPostPrintNotificationSettingsUpdate( orderStatus, { [ state.name ]: state.value }, expectedBody ); + } ); + } ); + describe( '#convertToApiPackage', () => { it( 'totals value correctly (by quantity)', () => { const pckg = { diff --git a/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/rates-step/test/shipping-rate.js b/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/rates-step/test/shipping-rate.js index 745461383..9a9101ca1 100644 --- a/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/rates-step/test/shipping-rate.js +++ b/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/rates-step/test/shipping-rate.js @@ -8,6 +8,7 @@ import { expect } from 'chai'; import { configure, mount } from 'enzyme'; import Adapter from 'enzyme-adapter-react-16' import { CheckboxControl, RadioControl } from '@wordpress/components'; +import { moment } from 'i18n-calypso'; /** * Internal dependencies @@ -94,7 +95,9 @@ describe( 'ShippingRate', () => { } ); it( 'renders the delivery date', () => { - expect( shippingRateWrapper ).to.contain(
January 1
); // eslint-disable-line + const expectedDate = moment( shippingRateWrapper.props().rateObject.delivery_date ).format( 'LL' ).split( ',' )[0]; + + expect( shippingRateWrapper ).to.contain(
{ expectedDate }
); // eslint-disable-line } ); } ); diff --git a/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/sidebar.js b/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/sidebar.js index 9d419494b..932d6b85c 100644 --- a/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/sidebar.js +++ b/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/sidebar.js @@ -27,8 +27,6 @@ import { getShippingLabel, isLoaded, getFormErrors, - shouldFulfillOrder, - shouldEmailDetails, hasSelectedRates, } from 'woocommerce/woocommerce-services/state/shipping-label/selectors'; import { getOrderWithEdits, isCurrentlyEditingOrder } from 'woocommerce/state/ui/orders/selectors'; @@ -51,10 +49,13 @@ export const Sidebar = props => { } = props; const onFulfillAndEmailOrderChange = ( value ) => { - // Don't change order status if already finished. - props.setFulfillOrderOption( orderId, siteId, value && ! isOrderFinished( order.status ) ); - // Email only if order is already complete. - props.setEmailDetailsOption( orderId, siteId, value && isOrderFinished( order.status ) ); + if ( isOrderFinished( order.status ) ) { + // Email only if order is already complete. + props.setEmailDetailsOption( orderId, siteId, value ); + } else { + // Don't change order status if already finished. + props.setFulfillOrderOption( orderId, siteId, value ); + } }; const onPaperSizeChange = value => props.updatePaperSize( orderId, siteId, value ); @@ -86,7 +87,10 @@ export const Sidebar = props => { translate( 'Notify the customer with shipment details' ) : translate( 'Mark this order as complete and notify the customer' ) } - checked={ fulfillOrder || emailDetails } + checked={ isOrderFinished( order.status ) ? + emailDetails : + fulfillOrder + } onChange={ onFulfillAndEmailOrderChange } /> @@ -118,8 +122,8 @@ const mapStateToProps = ( state, { orderId, siteId } ) => { form: shippingLabel.form, hasLabelsPaymentMethod: Boolean( getSelectedPaymentMethodId( state, siteId ) ), errors: loaded && getFormErrors( state, orderId, siteId ).sidebar, - fulfillOrder: loaded && shouldFulfillOrder( state, orderId, siteId ), - emailDetails: loaded && shouldEmailDetails( state, orderId, siteId ), + fulfillOrder: shippingLabel.fulfillOrder, + emailDetails: shippingLabel.emailDetails, }; }; diff --git a/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/test/sidebar.js b/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/test/sidebar.js index 85f70b186..ccd0a4cf2 100644 --- a/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/test/sidebar.js +++ b/client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/test/sidebar.js @@ -27,7 +27,7 @@ function createSidebarWrapper( initProps = {} ) { }, paperSize: 'letter', errors: {}, - form: { + form: { origin: { values: { country: 'US' } }, rates: {}, }, @@ -65,8 +65,7 @@ describe( 'Sidebar', () => { renderedCheckboxControl.props().onChange( false ) expect( props.setFulfillOrderOption.mock.calls ).to.have.lengthOf( 1 ); expect( props.setFulfillOrderOption.mock.calls[0][2] ).to.equal( false ); - expect( props.setEmailDetailsOption.mock.calls ).to.have.lengthOf( 1 ); - expect( props.setEmailDetailsOption.mock.calls[0][2] ).to.equal( false ); + expect( props.setEmailDetailsOption.mock.calls ).to.have.lengthOf( 0 ); } ); it( 'it is checked', function() { @@ -83,7 +82,7 @@ describe( 'Sidebar', () => { } ); describe( 'for completed orders', () => { - const { wrapper } = createSidebarWrapper( { order: { status: 'completed' }, fulfillOrder: false, emailDetails: false } ); + const { wrapper, props } = createSidebarWrapper( { order: { status: 'completed' }, fulfillOrder: false, emailDetails: false } ); const renderedCheckboxControl = wrapper.find( CheckboxControl ); it( 'Has a the Correct Label', function () { @@ -93,6 +92,13 @@ describe( 'Sidebar', () => { it( 'it is not checked', function() { expect( renderedCheckboxControl.props().checked ).to.equal( false ); } ); + + it( 'Unchecked checkbox disables sending email', function() { + renderedCheckboxControl.props().onChange( false ); + expect( props.setFulfillOrderOption.mock.calls ).to.have.lengthOf( 0 ); + expect( props.setEmailDetailsOption.mock.calls ).to.have.lengthOf( 1 ); + expect( props.setEmailDetailsOption.mock.calls[0][2] ).to.equal( false ); + } ); } ); describe( 'for no payment method and no selected rates', () => { const { wrapper } = createSidebarWrapper( { hasLabelsPaymentMethod: false } ); @@ -113,7 +119,7 @@ describe( 'Sidebar', () => { origin: { values: { country: 'US' } }, rates: upsFormRates, }, - hasLabelsPaymentMethod: false + hasLabelsPaymentMethod: false } ); it( 'has paper size dropdown', function () { @@ -132,7 +138,7 @@ describe( 'Sidebar', () => { origin: { values: { country: 'US' } }, rates: uspsFormRates, }, - hasLabelsPaymentMethod: false + hasLabelsPaymentMethod: false } ); it( 'does not have paper size dropdown', function () { diff --git a/tests/php/classes/test-class-wc-rest-connect-post-print-notification-settings-controller.php b/tests/php/classes/test-class-wc-rest-connect-post-print-notification-settings-controller.php new file mode 100644 index 000000000..dc47ea17a --- /dev/null +++ b/tests/php/classes/test-class-wc-rest-connect-post-print-notification-settings-controller.php @@ -0,0 +1,115 @@ +getMockBuilder( WC_Connect_API_Client_Live::class ) + ->disableOriginalConstructor() + ->getMock(); + + $this->settings_store_mock = $this->createMock( WC_Connect_Service_Settings_Store::class ); + $this->connect_logger_mock = $this->createMock( WC_Connect_Logger::class ); + + $this->controller = new WC_REST_Connect_Post_Print_Notification_Settings_Controller( $api_client_mock, $this->settings_store_mock, $this->connect_logger_mock ); + } + + public function test_it_updates_the_setting() { + $request = array( + 'name' => 'foo', + 'enabled' => true, + ); + + $this->settings_store_mock->expects( $this->once() ) + ->method( 'set_post_print_notification_setting' ) + ->with( 'foo', true ); + + $result = $this->controller->post( $request ); + + $this->assertEquals( new WP_REST_Response( array( 'success' => true ), 200 ), $result ); + } + + public function test_it_returns_wp_error_if_error_occurs() { + $request = array( + 'name' => 'foo', + 'enabled' => true, + ); + + $store_wp_error = new WP_Error( + 'some code', + 'some message' + ); + + $this->settings_store_mock->expects( $this->once() ) + ->method( 'set_post_print_notification_setting' ) + ->willReturn( $store_wp_error ); + + $expected_wp_error = new WP_Error( + 'save_failed', + sprintf( + __( 'Unable to update notification setting. %s', 'woocommerce-services' ), + $store_wp_error->get_error_message() + ), + array( 'status' => 400 ) + ); + + $result = $this->controller->post( $request ); + + $this->assertEquals( $expected_wp_error, $result ); + } + + public function test_it_logs_wp_error_if_it_occurs() { + $request = array( + 'name' => 'foo', + 'enabled' => true, + ); + + $store_wp_error = new WP_Error( + 'some code', + 'some message' + ); + + $this->settings_store_mock->expects( $this->once() ) + ->method( 'set_post_print_notification_setting' ) + ->willReturn( $store_wp_error ); + + $expected_logged_wp_error = new WP_Error( + 'save_failed', + sprintf( + __( 'Unable to update notification setting. %s', 'woocommerce-services' ), + $store_wp_error->get_error_message() + ), + array( 'status' => 400 ) + ); + + $this->connect_logger_mock->expects( $this->once() ) + ->method( 'log' ) + ->with( $expected_logged_wp_error, WC_REST_Connect_Post_Print_Notification_Settings_Controller::class ); + + $this->controller->post( $request ); + } +} diff --git a/tests/php/test_class-wc-connect-service-settings-store.php b/tests/php/test_class-wc-connect-service-settings-store.php index 6b97e0013..6404e00f1 100644 --- a/tests/php/test_class-wc-connect-service-settings-store.php +++ b/tests/php/test_class-wc-connect-service-settings-store.php @@ -180,4 +180,97 @@ public function test_get_label_order_meta_data_invalid_string() { $this->assertEquals( $actual, $expected ); } + + public function test_get_notification_settings() { + $expected = array( + 'mark_order_complete_and_notify_customer' => true, + 'notify_customer_with_shipment_details' => false, + ); + + WC_Connect_Options::update_option( 'post_print_notification_settings', $expected ); + + $settings_store = $this->get_settings_store(); + $actual = $settings_store->get_post_print_notification_settings(); + + $this->assertEquals( $expected, $actual ); + } + + public function test_get_notification_settings_returns_defaults_if_settings_are_empty() { + WC_Connect_Options::delete_option( 'post_print_notification_settings' ); + + $expected = array( + 'mark_order_complete_and_notify_customer' => false, + 'notify_customer_with_shipment_details' => false, + ); + + $settings_store = $this->get_settings_store(); + $actual = $settings_store->get_post_print_notification_settings(); + + $this->assertEquals( $expected, $actual ); + } + + public function test_get_notification_settings_fills_missing_options_with_defaults() { + $partial_settings = array( + 'mark_order_complete_and_notify_customer' => true, + ); + + WC_Connect_Options::update_option( 'post_print_notification_settings', $partial_settings ); + + $expected = array( + 'mark_order_complete_and_notify_customer' => true, + 'notify_customer_with_shipment_details' => false, + ); + + $settings_store = $this->get_settings_store(); + $actual = $settings_store->get_post_print_notification_settings(); + + $this->assertEquals( $expected, $actual ); + } + + public function test_set_notification_setting_updates_settings() { + WC_Connect_Options::delete_option( 'post_print_notification_settings' ); + + $settings_store = $this->get_settings_store(); + $settings_store->set_post_print_notification_setting( 'mark_order_complete_and_notify_customer', true ); + $settings_store->set_post_print_notification_setting( 'notify_customer_with_shipment_details', true ); + + $settings = $settings_store->get_post_print_notification_settings(); + + $this->assertTrue( $settings['mark_order_complete_and_notify_customer'] ); + $this->assertTrue( $settings['notify_customer_with_shipment_details'] ); + } + + public function test_set_notification_setting_returns_error_for_invalid_setting_names() { + $settings_store = $this->get_settings_store(); + $result = $settings_store->set_post_print_notification_setting( 'not a valid setting name', true ); + + $this->assertInstanceOf( 'WP_Error', $result ); + $this->assertEquals( 'invalid_notification_setting_name', $result->get_error_code() ); + } + + public function test_set_notification_setting_casts_values_to_bool() { + WC_Connect_Options::delete_option( 'post_print_notification_settings' ); + + $settings_store = $this->get_settings_store(); + $settings_store->set_post_print_notification_setting( 'mark_order_complete_and_notify_customer', 'foo' ); + $settings_store->set_post_print_notification_setting( 'notify_customer_with_shipment_details', '' ); + + $settings = $settings_store->get_post_print_notification_settings(); + + $this->assertSame( true, $settings['mark_order_complete_and_notify_customer'] ); + $this->assertSame( false, $settings['notify_customer_with_shipment_details'] ); + } + + public function test_set_notfication_setting_returns_true_when_setting_same_value_as_before() { + $settings = array( + 'mark_order_complete_and_notify_customer' => true, + 'notify_customer_with_shipment_details' => true, + ); + WC_Connect_Options::update_option( 'post_print_notification_settings', $settings ); + + $settings_store = $this->get_settings_store(); + $result = $settings_store->set_post_print_notification_setting( 'mark_order_complete_and_notify_customer', true ); + + $this->assertTrue( $result ); + } } diff --git a/woocommerce-services.php b/woocommerce-services.php index 697148690..74ac108b1 100644 --- a/woocommerce-services.php +++ b/woocommerce-services.php @@ -98,6 +98,11 @@ class WC_Connect_Loader { */ protected $rest_account_settings_controller; + /** + * @var WC_REST_Connect_Post_Print_Notification_Settings_Controller + */ + protected $rest_post_print_notification_settings_controller; + /** * @var WC_REST_Connect_Packages_Controller */ @@ -327,6 +332,10 @@ public function get_rest_account_settings_controller() { return $this->rest_account_settings_controller; } + public function get_rest_post_print_notification_settings_controller() { + return $this->rest_post_print_notification_settings_controller; + } + public function set_rest_tos_controller( WC_REST_Connect_Tos_Controller $rest_tos_controller ) { $this->rest_tos_controller = $rest_tos_controller; } @@ -363,6 +372,10 @@ public function set_rest_account_settings_controller( WC_REST_Connect_Account_Se $this->rest_account_settings_controller = $rest_account_settings_controller; } + public function set_rest_post_print_notification_settings_controller( WC_REST_Connect_Post_Print_Notification_Settings_Controller $rest_post_print_notification_settings_controller ) { + $this->rest_post_print_notification_settings_controller = $rest_post_print_notification_settings_controller; + } + public function get_rest_services_controller() { return $this->rest_services_controller; } @@ -826,6 +839,11 @@ public function rest_api_init() { $this->set_rest_account_settings_controller( $rest_account_settings_controller ); $rest_account_settings_controller->register_routes(); + require_once( plugin_basename( 'classes/class-wc-rest-connect-post-print-notification-settings-controller.php' ) ); + $rest_post_print_notification_settings_controller = new WC_REST_Connect_Post_Print_Notification_Settings_Controller( $this->api_client, $settings_store, $logger ); + $this->set_rest_post_print_notification_settings_controller( $rest_post_print_notification_settings_controller ); + $rest_post_print_notification_settings_controller->register_routes(); + require_once( plugin_basename( 'classes/class-wc-rest-connect-services-controller.php' ) ); $rest_services_controller = new WC_REST_Connect_Services_Controller( $this->api_client, $settings_store, $logger, $schemas_store ); $this->set_rest_services_controller( $rest_services_controller );