diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/ConfirmEmail.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/ConfirmEmail.php
new file mode 100644
index 00000000000..4d6287c73c2
--- /dev/null
+++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/ConfirmEmail.php
@@ -0,0 +1,81 @@
+emailValidator->isValid($args['input']['email'])) {
+ throw new GraphQlInputException(__('Email is invalid'));
+ }
+ try {
+ $customer = $this->accountManagement->activate($args['input']['email'], $args['input']['confirmation_key']);
+ } catch (InvalidTransitionException | InputMismatchException $e) {
+ throw new GraphQlInputException(__($e->getRawMessage()));
+ } catch (StateException) {
+ throw new GraphQlInputException(__('This confirmation key is invalid or has expired.'));
+ } catch (\Exception) {
+ throw new GraphQlInputException(__('There was an error confirming the account'));
+ }
+ return ['customer' => $this->extractCustomerData->execute($customer)];
+ }
+}
diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/ConfirmationStatus.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/ConfirmationStatus.php
new file mode 100644
index 00000000000..70ef16bc5cb
--- /dev/null
+++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/ConfirmationStatus.php
@@ -0,0 +1,58 @@
+accountManagement->getConfirmationStatus($context->getUserId());
+ } catch (LocalizedException $e) {
+ throw new GraphQlInputException(__($e->getMessage()), $e);
+ }
+ return strtoupper($confirmationStatus);
+ }
+}
diff --git a/app/code/Magento/CustomerGraphQl/etc/graphql/di.xml b/app/code/Magento/CustomerGraphQl/etc/graphql/di.xml
index 0636098cd6d..305e9cd12d6 100644
--- a/app/code/Magento/CustomerGraphQl/etc/graphql/di.xml
+++ b/app/code/Magento/CustomerGraphQl/etc/graphql/di.xml
@@ -37,6 +37,7 @@
- customer/password/required_character_classes_number
- customer/password/minimum_password_length
- customer/password/autocomplete_on_storefront
+ - customer/create_account/confirm
diff --git a/app/code/Magento/CustomerGraphQl/etc/schema.graphqls b/app/code/Magento/CustomerGraphQl/etc/schema.graphqls
index fd148e12e70..848d0a9be8d 100644
--- a/app/code/Magento/CustomerGraphQl/etc/schema.graphqls
+++ b/app/code/Magento/CustomerGraphQl/etc/schema.graphqls
@@ -5,6 +5,7 @@ type StoreConfig {
required_character_classes_number : String @doc(description: "The number of different character classes (lowercase, uppercase, digits, special characters) required in a password.")
minimum_password_length : String @doc(description: "The minimum number of characters required for a valid password.")
autocomplete_on_storefront : Boolean @doc(description: "Indicates whether to enable autocomplete on login and forgot password forms.")
+ create_account_confirmation: Boolean @doc(description: "Indicates if the new accounts need confirmation.")
}
type Query {
@@ -29,6 +30,12 @@ type Mutation {
requestPasswordResetEmail(email: String! @doc(description: "The customer's email address.")): Boolean @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\RequestPasswordResetEmail") @doc(description: "Request an email with a reset password token for the registered customer identified by the specified email.")
resetPassword(email: String! @doc(description: "The customer's email address."), resetPasswordToken: String! @doc(description: "A runtime token generated by the `requestPasswordResetEmail` mutation."), newPassword: String! @doc(description: "The customer's new password.")): Boolean @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\ResetPassword") @doc(description: "Reset a customer's password using the reset password token that the customer received in an email after requesting it using `requestPasswordResetEmail`.")
updateCustomerEmail(email: String! @doc(description: "The customer's email address."), password: String! @doc(description: "The customer's password.")): CustomerOutput @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\UpdateCustomerEmail") @doc(description: "Change the email address for the logged-in customer.")
+ confirmEmail(input: ConfirmEmailInput! @doc(description: "An input object to identify the customer to confirm the email.")): CustomerOutput @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\ConfirmEmail") @doc(description: "Confirms the email address for a customer.")
+}
+
+input ConfirmEmailInput @doc(description: "Contains details about a customer email address to confirm.") {
+ email: String! @doc(description: "The email address to be confirmed.")
+ confirmation_key: String! @doc(description: "The key to confirm the email address.")
}
input CustomerAddressInput @doc(description: "Contains details about a billing or shipping address."){
@@ -140,6 +147,7 @@ type Customer @doc(description: "Defines the customer name, addresses, and other
addresses: [CustomerAddress] @doc(description: "An array containing the customer's shipping and billing addresses.") @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\CustomerAddresses")
gender: Int @doc(description: "The customer's gender (Male - 1, Female - 2).")
custom_attributes(attributeCodes: [ID!]): [AttributeValueInterface] @doc(description: "Customer's custom attributes.") @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\CustomAttributeFilter")
+ confirmation_status: ConfirmationStatusEnum! @doc(description: "The customer's confirmation status.") @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\ConfirmationStatus")
}
type CustomerAddress @doc(description: "Contains detailed information about a customer's billing or shipping address."){
@@ -467,3 +475,8 @@ enum ValidationRuleEnum @doc(description: "List of validation rule names applied
MAX_IMAGE_HEIGHT
MAX_IMAGE_WIDTH
}
+
+enum ConfirmationStatusEnum @doc(description: "List of account confirmation statuses.") {
+ ACCOUNT_CONFIRMED @doc(description: "Account confirmed")
+ ACCOUNT_CONFIRMATION_NOT_REQUIRED @doc(description: "Account confirmation not required")
+}
diff --git a/app/code/Magento/IntegrationGraphQl/README.md b/app/code/Magento/IntegrationGraphQl/README.md
new file mode 100644
index 00000000000..d6414fad7f7
--- /dev/null
+++ b/app/code/Magento/IntegrationGraphQl/README.md
@@ -0,0 +1,22 @@
+# Magento_IntegrationGraphQl module
+
+This module provides GraphQl resolvers for Integartion module.
+
+## Installation
+
+Before installing this module, note that the Magento_IntegrationGraphQl is dependent on the following modules:
+
+- `Magento_GraphQl`
+- `Magento_Integration`
+
+For information about a module installation in Magento 2, see [Enable or disable modules](https://experienceleague.adobe.com/docs/commerce-operations/installation-guide/tutorials/manage-modules.html).
+
+## Extensibility
+
+Extension developers can interact with the Magento_IntegrationGraphQl module. For more information about the Magento extension mechanism, see [Magento plugins](https://developer.adobe.com/commerce/php/development/components/plugins/).
+
+[The Magento dependency injection mechanism](https://developer.adobe.com/commerce/php/development/components/dependency-injection/) enables you to override the functionality of the Magento_IntegrationGraphQl module.
+
+## Additional information
+
+You can get more information about [GraphQl In Magento 2](https://developer.adobe.com/commerce/webapi/graphql/).
diff --git a/app/code/Magento/IntegrationGraphQl/composer.json b/app/code/Magento/IntegrationGraphQl/composer.json
new file mode 100644
index 00000000000..bb26e5f2af1
--- /dev/null
+++ b/app/code/Magento/IntegrationGraphQl/composer.json
@@ -0,0 +1,21 @@
+{
+ "name": "magento/module-integration-graph-ql",
+ "description": "N/A",
+ "type": "magento2-module",
+ "require": {
+ "php": "~8.1.0||~8.2.0||~8.3.0",
+ "magento/framework": "*"
+ },
+ "license": [
+ "OSL-3.0",
+ "AFL-3.0"
+ ],
+ "autoload": {
+ "files": [
+ "registration.php"
+ ],
+ "psr-4": {
+ "Magento\\IntegrationGraphQl\\": ""
+ }
+ }
+}
diff --git a/app/code/Magento/IntegrationGraphQl/etc/graphql/di.xml b/app/code/Magento/IntegrationGraphQl/etc/graphql/di.xml
new file mode 100644
index 00000000000..9e0541e944c
--- /dev/null
+++ b/app/code/Magento/IntegrationGraphQl/etc/graphql/di.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+ - oauth/access_token_lifetime/customer
+
+
+
+
diff --git a/app/code/Magento/IntegrationGraphQl/etc/module.xml b/app/code/Magento/IntegrationGraphQl/etc/module.xml
new file mode 100644
index 00000000000..ca4c956afc4
--- /dev/null
+++ b/app/code/Magento/IntegrationGraphQl/etc/module.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/IntegrationGraphQl/etc/schema.graphqls b/app/code/Magento/IntegrationGraphQl/etc/schema.graphqls
new file mode 100644
index 00000000000..1241f54dca1
--- /dev/null
+++ b/app/code/Magento/IntegrationGraphQl/etc/schema.graphqls
@@ -0,0 +1,18 @@
+# ADOBE CONFIDENTIAL
+# ___________________
+#
+# Copyright 2024 Adobe
+# All Rights Reserved.
+#
+# NOTICE: All information contained herein is, and remains
+# the property of Adobe and its suppliers, if any. The intellectual
+# and technical concepts contained herein are proprietary to Adobe
+# and its suppliers and are protected by all applicable intellectual
+# property laws, including trade secret and copyright laws.
+# Dissemination of this information or reproduction of this material
+# is strictly forbidden unless prior written permission is obtained
+# from Adobe.
+
+type StoreConfig {
+ customer_access_token_lifetime: Float @doc(description: "Customer access token lifetime.")
+}
diff --git a/app/code/Magento/IntegrationGraphQl/registration.php b/app/code/Magento/IntegrationGraphQl/registration.php
new file mode 100644
index 00000000000..bb35a050bf7
--- /dev/null
+++ b/app/code/Magento/IntegrationGraphQl/registration.php
@@ -0,0 +1,19 @@
+checkout/options/guest_checkout
- checkout/options/onepage_checkout_enabled
- checkout/options/max_items_display_count
+ - checkout/cart_link/use_qty
+ - checkout/sidebar/display
+ - checkout/sidebar/max_items_display_count
+ - checkout/cart/delete_quote_after
diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls
index 9f44a24b197..53da2d87511 100644
--- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls
+++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls
@@ -260,7 +260,7 @@ type ApplyCouponToCartOutput @doc(description: "Contains details about the cart
type PlaceOrderOutput @doc(description: "Contains the results of the request to place an order.") {
order: Order @deprecated(reason: "Use `orderV2` instead.") @doc(description: "The ID of the order.")
- orderV2: CustomerOrder! @doc(description: "Full order information.")
+ orderV2: CustomerOrder @doc(description: "Full order information.")
errors: [PlaceOrderError!]! @doc(description:"An array of place order errors.")
}
@@ -511,6 +511,10 @@ type StoreConfig {
is_guest_checkout_enabled: Boolean @doc(description: "Extended Config Data - checkout/options/guest_checkout")
is_one_page_checkout_enabled: Boolean @doc(description: "Extended Config Data - checkout/options/onepage_checkout_enabled")
max_items_in_order_summary: Int @doc(description: "Extended Config Data - checkout/options/max_items_display_count")
+ cart_summary_display_quantity: Int @doc(description: "Extended Config Data - checkout/cart_link/use_qty")
+ minicart_display: Boolean @doc(description: "Extended Config Data - checkout/sidebar/display")
+ minicart_max_items: Int @doc(description: "Extended Config Data - checkout/sidebar/count")
+ cart_expires_in_days: Int @doc(description: "Extended Config Data - checkout/cart/delete_quote_after")
}
input EstimateTotalsInput {
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsSection.xml
index 0497bdbeb26..ef359ce11ea 100644
--- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsSection.xml
+++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsSection.xml
@@ -36,6 +36,8 @@
+
+
diff --git a/app/code/Magento/SalesGraphQl/Model/Formatter/Order.php b/app/code/Magento/SalesGraphQl/Model/Formatter/Order.php
index ec41c15e0fc..a1ad36d4dfb 100644
--- a/app/code/Magento/SalesGraphQl/Model/Formatter/Order.php
+++ b/app/code/Magento/SalesGraphQl/Model/Formatter/Order.php
@@ -17,26 +17,14 @@
*/
class Order
{
- /**
- * @var OrderAddress
- */
- private $orderAddress;
-
- /**
- * @var OrderPayments
- */
- private $orderPayments;
-
/**
* @param OrderAddress $orderAddress
* @param OrderPayments $orderPayments
*/
public function __construct(
- OrderAddress $orderAddress,
- OrderPayments $orderPayments
+ private readonly OrderAddress $orderAddress,
+ private readonly OrderPayments $orderPayments
) {
- $this->orderAddress = $orderAddress;
- $this->orderPayments = $orderPayments;
}
/**
@@ -57,6 +45,7 @@ public function format(OrderInterface $orderModel): array
'order_date' => $orderModel->getCreatedAt(),
'order_number' => $orderModel->getIncrementId(),
'status' => $orderModel->getStatusLabel(),
+ 'email' => $orderModel->getCustomerEmail(),
'shipping_method' => $orderModel->getShippingDescription(),
'shipping_address' => $this->orderAddress->getOrderShippingAddress($orderModel),
'billing_address' => $this->orderAddress->getOrderBillingAddress($orderModel),
diff --git a/app/code/Magento/SalesGraphQl/etc/schema.graphqls b/app/code/Magento/SalesGraphQl/etc/schema.graphqls
index b1d1739694d..1e2991d7fed 100644
--- a/app/code/Magento/SalesGraphQl/etc/schema.graphqls
+++ b/app/code/Magento/SalesGraphQl/etc/schema.graphqls
@@ -74,6 +74,7 @@ type CustomerOrder @doc(description: "Contains details about each of the custome
grand_total: Float @deprecated(reason: "Use the `totals.grand_total` field instead.")
token: String! @doc(description: "The token that can be used to retrieve the order using order query.") @resolver(class: "Magento\\SalesGraphQl\\Model\\Resolver\\Token")
applied_coupons: [AppliedCoupon!]! @doc(description: "Coupons applied to the order.")
+ email: String @doc(description: "Order customer email.")
}
type OrderAddress @doc(description: "Contains detailed information about an order's billing and shipping addresses."){
diff --git a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml
index a7f2da506e8..f76a1d49358 100644
--- a/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml
+++ b/app/code/Magento/SalesRule/Test/Mftf/Data/SalesRuleData.xml
@@ -604,4 +604,39 @@
Percent of product price discount
10
+
+
+ SimpleSalesRule
+ Sales Rule Description
+
+ - 1
+
+
+ - 1
+
+ 10
+ true
+ false
+ true
+ 1
+ by_fixed
+ 10
+ 10
+ 0
+ false
+ 0
+ false
+ SPECIFIC_COUPON
+ false
+ 10
+ 1
+
+
+
+ false
+
+
+ 3
+ true
+
diff --git a/app/code/Magento/TaxGraphQl/Model/Resolver/DisplayWrapping.php b/app/code/Magento/TaxGraphQl/Model/Resolver/DisplayWrapping.php
new file mode 100644
index 00000000000..bc85bcd6249
--- /dev/null
+++ b/app/code/Magento/TaxGraphQl/Model/Resolver/DisplayWrapping.php
@@ -0,0 +1,54 @@
+enumLookup->getEnumValueFromField(
+ 'TaxWrappingEnum',
+ $value['shopping_cart_display_tax_gift_wrapping']
+ );
+ }
+ return null;
+ }
+}
diff --git a/app/code/Magento/TaxGraphQl/etc/graphql/di.xml b/app/code/Magento/TaxGraphQl/etc/graphql/di.xml
index a0316135e46..601a81b7476 100644
--- a/app/code/Magento/TaxGraphQl/etc/graphql/di.xml
+++ b/app/code/Magento/TaxGraphQl/etc/graphql/di.xml
@@ -16,7 +16,8 @@
* ************************************************************************
*/
-->
-
+
@@ -26,7 +27,21 @@
- tax/cart_display/grandtotal
- tax/cart_display/full_summary
- tax/cart_display/zero_tax
+ - tax/cart_display/gift_wrapping
+
+
+
+
+
+
+ -
+
- 1
+ - 2
+ - 3
+
+
+
diff --git a/app/code/Magento/TaxGraphQl/etc/schema.graphqls b/app/code/Magento/TaxGraphQl/etc/schema.graphqls
index e6234b83539..2696098dbaa 100644
--- a/app/code/Magento/TaxGraphQl/etc/schema.graphqls
+++ b/app/code/Magento/TaxGraphQl/etc/schema.graphqls
@@ -12,4 +12,11 @@ type StoreConfig {
shopping_cart_display_grand_total: Boolean @doc(description: "Extended Config Data - tax/cart_display/grandtotal")
shopping_cart_display_full_summary: Boolean @doc(description: "Extended Config Data - tax/cart_display/full_summary")
shopping_cart_display_zero_tax: Boolean @doc(description: "Extended Config Data - tax/cart_display/zero_tax")
+ shopping_cart_display_tax_gift_wrapping: TaxWrappingEnum @doc(description: "Extended Config Data - tax/cart_display/gift_wrapping") @resolver(class: "Magento\\TaxGraphQl\\Model\\Resolver\\DisplayWrapping")
+}
+
+enum TaxWrappingEnum {
+ DISPLAY_EXCLUDING_TAX
+ DISPLAY_INCLUDING_TAX
+ DISPLAY_TYPE_BOTH
}
diff --git a/composer.json b/composer.json
index c8a0fe02966..444e7146a38 100644
--- a/composer.json
+++ b/composer.json
@@ -206,6 +206,7 @@
"magento/module-indexer": "*",
"magento/module-instant-purchase": "*",
"magento/module-integration": "*",
+ "magento/module-integration-graph-ql": "*",
"magento/module-layered-navigation": "*",
"magento/module-login-as-customer": "*",
"magento/module-login-as-customer-admin-ui": "*",
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ConfirmEmailTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ConfirmEmailTest.php
new file mode 100644
index 00000000000..4b6fa08cd27
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ConfirmEmailTest.php
@@ -0,0 +1,160 @@
+ 'customer@example.com',
+ 'confirmation' => 'abcde',
+ ],
+ 'customer'
+ )
+]
+class ConfirmEmailTest extends GraphQlAbstract
+{
+ private const QUERY = <<graphQlMutation(
+ sprintf(
+ self::QUERY,
+ 'customer@example.com',
+ 'abcde',
+ ),
+ [],
+ '',
+ $this->getCustomerAuthHeaders('customer@example.com', self::PASSWORD)
+ );
+
+ $this->assertEquals(
+ [
+ 'confirmEmail' => [
+ 'customer' => [
+ 'email' => 'customer@example.com'
+ ]
+ ]
+ ],
+ $response
+ );
+
+ $this->expectException(\Exception::class);
+ $this->expectExceptionMessage('The account is already active.');
+
+ $this->graphQlMutation(
+ sprintf(
+ self::QUERY,
+ 'customer@example.com',
+ 'abcde',
+ ),
+ [],
+ '',
+ $this->getCustomerAuthHeaders('customer@example.com', self::PASSWORD)
+ );
+ }
+
+ /**
+ * @return void
+ * @throws AuthenticationException
+ */
+ public function testConfirmEmailWrongEmail()
+ {
+ $this->expectException(\Exception::class);
+ $this->expectExceptionMessage('Email is invalid');
+
+ $this->graphQlMutation(
+ sprintf(
+ self::QUERY,
+ 'bad-email',
+ 'abcde',
+ ),
+ [],
+ '',
+ $this->getCustomerAuthHeaders('customer@example.com', self::PASSWORD)
+ );
+ }
+
+ /**
+ * @return void
+ * @throws AuthenticationException
+ */
+ public function testConfirmEmailWrongConfirmation()
+ {
+ $this->expectException(\Exception::class);
+ $this->expectExceptionMessage('The confirmation token is invalid. Verify the token and try again.');
+
+ $this->graphQlMutation(
+ sprintf(
+ self::QUERY,
+ 'customer@example.com',
+ 'wrong-confirmation',
+ ),
+ [],
+ '',
+ $this->getCustomerAuthHeaders('customer@example.com', self::PASSWORD)
+ );
+ }
+
+ /**
+ * @param string $email
+ * @param string $password
+ * @return array
+ * @throws AuthenticationException
+ */
+ private function getCustomerAuthHeaders(string $email, string $password): array
+ {
+ $customerToken = Bootstrap::getObjectManager()->get(
+ CustomerTokenServiceInterface::class
+ )->createCustomerAccessToken(
+ $email,
+ $password
+ );
+ return ['Authorization' => 'Bearer ' . $customerToken];
+ }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ConfirmationStatusTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ConfirmationStatusTest.php
new file mode 100644
index 00000000000..e2e05392917
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/ConfirmationStatusTest.php
@@ -0,0 +1,188 @@
+customerTokenService = Bootstrap::getObjectManager()->get(CustomerTokenServiceInterface::class);
+ $this->customerRepository = Bootstrap::getObjectManager()->get(CustomerRepositoryInterface::class);
+ }
+
+ #[
+ Config('customer/create_account/confirm', 0),
+ DataFixture(
+ Customer::class,
+ [
+ 'email' => 'customer@example.com',
+ ],
+ 'customer'
+ )
+ ]
+ public function testGetConfirmationStatusConfirmationNotRequiredTest()
+ {
+ $customer = DataFixtureStorageManager::getStorage()->get('customer');
+ $query = <<graphQlQuery(
+ $query,
+ [],
+ '',
+ $this->getHeaderMap($customer->getEmail(), 'password')
+ );
+ $this->assertEquals(
+ strtoupper(AccountManagementInterface::ACCOUNT_CONFIRMATION_NOT_REQUIRED),
+ $response['customer']['confirmation_status']
+ );
+ }
+
+ #[
+ Config('customer/create_account/confirm', 1),
+ DataFixture(
+ Customer::class,
+ [
+ 'email' => 'customer@example.com',
+ ],
+ 'customer'
+ )
+ ]
+ public function testGetConfirmationStatusConfirmedTest()
+ {
+ $customer = DataFixtureStorageManager::getStorage()->get('customer');
+ $query = <<graphQlQuery(
+ $query,
+ [],
+ '',
+ $this->getHeaderMap($customer->getEmail(), 'password')
+ );
+ $this->assertEquals(
+ strtoupper(AccountManagementInterface::ACCOUNT_CONFIRMED),
+ $response['customer']['confirmation_status']
+ );
+ }
+
+ #[
+ Config('customer/create_account/confirm', 1),
+ DataFixture(
+ Customer::class,
+ [
+ 'email' => 'another@example.com',
+ ],
+ 'customer'
+ )
+ ]
+ public function testGetConfirmationStatusConfirmationRequiredTest()
+ {
+ $this->expectExceptionMessage("This account isn't confirmed. Verify and try again.");
+ /** @var CustomerInterface $customer */
+ $customer = DataFixtureStorageManager::getStorage()->get('customer');
+ $headersMap = $this->getHeaderMap($customer->getEmail(), 'password');
+ $customer->setConfirmation(AccountManagementInterface::ACCOUNT_CONFIRMATION_REQUIRED);
+ $this->customerRepository->save($this->customerRepository->get($customer->getEmail()));
+ $query = <<graphQlQuery(
+ $query,
+ [],
+ '',
+ $headersMap
+ );
+ }
+
+ #[
+ DataFixture(
+ Customer::class,
+ [
+ 'email' => 'test@example.com',
+ ],
+ 'customer'
+ )
+ ]
+ public function testGetConfirmationStatusIfUserIsNotAuthorizedTest()
+ {
+ $this->expectException(\Exception::class);
+ $this->expectExceptionMessage('The current customer isn\'t authorized.');
+
+ $query = <<graphQlQuery($query);
+ }
+
+ /**
+ * @param string $email
+ * @param string $password
+ *
+ * @return array
+ * @throws AuthenticationException
+ */
+ private function getHeaderMap(string $email, string $password): array
+ {
+ $customerToken = $this->customerTokenService->createCustomerAccessToken($email, $password);
+ return ['Authorization' => 'Bearer ' . $customerToken];
+ }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/StoreConfigTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/StoreConfigTest.php
index 473105c2c46..99b9e95e8d1 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/StoreConfigTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/StoreConfigTest.php
@@ -8,6 +8,7 @@
namespace Magento\GraphQl\Customer;
use Exception;
+use Magento\TestFramework\Fixture\Config;
use Magento\TestFramework\TestCase\GraphQlAbstract;
/**
@@ -35,4 +36,38 @@ public function testReturnTypeAutocompleteOnStorefrontConfig()
self::assertArrayHasKey('autocomplete_on_storefront', $response['storeConfig']);
self::assertTrue($response['storeConfig']['autocomplete_on_storefront']);
}
+
+ #[
+ Config('customer/create_account/confirm', 1)
+ ]
+ public function testCreateAccountConfirmationEnabledStorefrontConfig()
+ {
+ $query = <<graphQlQuery($query);
+ self::assertArrayHasKey('create_account_confirmation', $response['storeConfig']);
+ self::assertTrue($response['storeConfig']['create_account_confirmation']);
+ }
+
+ #[
+ Config('customer/create_account/confirm', 0)
+ ]
+ public function testCreateAccountConfirmationDisabledStorefrontConfig()
+ {
+ $query = <<graphQlQuery($query);
+ self::assertArrayHasKey('create_account_confirmation', $response['storeConfig']);
+ self::assertFalse($response['storeConfig']['create_account_confirmation']);
+ }
}
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/IntegrationGraphQl/CustomerAccessTokenLifetimeResolverTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/IntegrationGraphQl/CustomerAccessTokenLifetimeResolverTest.php
new file mode 100644
index 00000000000..10bc66fc4a4
--- /dev/null
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/IntegrationGraphQl/CustomerAccessTokenLifetimeResolverTest.php
@@ -0,0 +1,85 @@
+assertEquals(
+ $this->graphQlQuery($this->getQuery()),
+ [
+ 'storeConfig' => [
+ "customer_access_token_lifetime" => 2
+ ]
+ ]
+ );
+ }
+
+ #[
+ Config('oauth/access_token_lifetime/customer', 2.5)
+ ]
+ public function testGetCustomerAccessTokenLifetimeAsFloat()
+ {
+ $this->assertEquals(
+ $this->graphQlQuery($this->getQuery()),
+ [
+ 'storeConfig' => [
+ "customer_access_token_lifetime" => 2.5
+ ]
+ ]
+ );
+ }
+
+ #[
+ Config('oauth/access_token_lifetime/customer', null)
+ ]
+ public function testGetCustomerAccessTokenLifetimeNull()
+ {
+ $this->assertEquals(
+ $this->graphQlQuery($this->getQuery()),
+ [
+ 'storeConfig' => [
+ "customer_access_token_lifetime" => null
+ ]
+ ]
+ );
+ }
+
+ /**
+ * @return string
+ */
+ private function getQuery(): string
+ {
+ return <<orderFactory->create();
@@ -147,7 +149,9 @@ public function testPlaceOrderWithAutoGroup()
self::assertArrayHasKey('placeOrder', $response);
self::assertArrayHasKey('order_number', $response['placeOrder']['order']);
+ self::assertArrayHasKey('number', $response['placeOrder']['orderV2']);
self::assertEquals($reservedOrderId, $response['placeOrder']['order']['order_number']);
+ self::assertEquals($reservedOrderId, $response['placeOrder']['orderV2']['number']);
self::assertEmpty(count($response['placeOrder']['errors']));
$orderIncrementId = $response['placeOrder']['order']['order_number'];
$order = $this->orderFactory->create();
@@ -458,7 +462,9 @@ public function testPlaceOrderWithGiftMessage()
self::assertArrayHasKey('placeOrder', $response);
self::assertArrayHasKey('order_number', $response['placeOrder']['order']);
+ self::assertArrayHasKey('number', $response['placeOrder']['orderV2']);
self::assertEquals($reservedOrderId, $response['placeOrder']['order']['order_number']);
+ self::assertEquals($reservedOrderId, $response['placeOrder']['orderV2']['number']);
$orderIncrementId = $response['placeOrder']['order']['order_number'];
$order = $this->orderFactory->create();
$order->loadByIncrementId($orderIncrementId);
@@ -477,6 +483,9 @@ private function getQuery(string $maskedQuoteId): string
order {
order_number
}
+ orderV2 {
+ number
+ }
errors {
message
code
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/StoreConfigResolverTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/StoreConfigResolverTest.php
index 0dbf16957ff..9e8bf05b3be 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/StoreConfigResolverTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/StoreConfigResolverTest.php
@@ -18,11 +18,28 @@
class StoreConfigResolverTest extends GraphQlAbstract
{
private const MAX_ITEMS_TO_DISPLAY = 5;
+ private const CART_SUMMARY_DISPLAY_TOTAL = 1;
+ private const MINICART_MAX_ITEMS = 10;
+ private const CART_EXPIRES_IN_DAYS = 5;
#[
ConfigFixture(Data::XML_PATH_GUEST_CHECKOUT, true, ScopeInterface::SCOPE_STORE, 'default'),
ConfigFixture('checkout/options/onepage_checkout_enabled', true, ScopeInterface::SCOPE_STORE, 'default'),
- ConfigFixture('checkout/options/max_items_display_count', self::MAX_ITEMS_TO_DISPLAY)
+ ConfigFixture('checkout/options/max_items_display_count', self::MAX_ITEMS_TO_DISPLAY),
+ ConfigFixture('checkout/cart_link/use_qty', 1, ScopeInterface::SCOPE_STORE, 'default'),
+ ConfigFixture('checkout/sidebar/display', true, ScopeInterface::SCOPE_STORE, 'default'),
+ ConfigFixture(
+ 'checkout/sidebar/max_items_display_count',
+ self::MINICART_MAX_ITEMS,
+ ScopeInterface::SCOPE_STORE,
+ 'default'
+ ),
+ ConfigFixture(
+ 'checkout/cart/delete_quote_after',
+ self::CART_EXPIRES_IN_DAYS,
+ ScopeInterface::SCOPE_STORE,
+ 'default'
+ ),
]
public function testGetStoreConfig(): void
{
@@ -32,7 +49,11 @@ public function testGetStoreConfig(): void
storeConfig {
is_guest_checkout_enabled,
is_one_page_checkout_enabled,
- max_items_in_order_summary
+ max_items_in_order_summary,
+ cart_summary_display_quantity,
+ minicart_display,
+ minicart_max_items,
+ cart_expires_in_days
}
}
QUERY;
@@ -52,5 +73,9 @@ private function validateStoreConfig(
$this->assertTrue($responseConfig['is_guest_checkout_enabled']);
$this->assertTrue($responseConfig['is_one_page_checkout_enabled']);
$this->assertEquals(self::MAX_ITEMS_TO_DISPLAY, $responseConfig['max_items_in_order_summary']);
+ $this->assertEquals(self::CART_SUMMARY_DISPLAY_TOTAL, $responseConfig['cart_summary_display_quantity']);
+ $this->assertTrue($responseConfig['minicart_display']);
+ $this->assertEquals(self::MINICART_MAX_ITEMS, $responseConfig['minicart_max_items']);
+ $this->assertEquals(self::CART_EXPIRES_IN_DAYS, $responseConfig['cart_expires_in_days']);
}
}
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Sales/GuestOrderByTokenTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Sales/GuestOrderByTokenTest.php
index f25c54d57a1..959d21b3e5d 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Sales/GuestOrderByTokenTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Sales/GuestOrderByTokenTest.php
@@ -48,6 +48,7 @@ class GuestOrderByTokenTest extends GraphQlAbstract
token: "%token"
}) {
number
+ email
billing_address {
firstname
lastname
@@ -63,6 +64,7 @@ class GuestOrderByTokenTest extends GraphQlAbstract
}) {
orderV2 {
number
+ email
billing_address {
firstname
lastname
@@ -97,6 +99,7 @@ public function testGuestOrder(): void
$this->assertNotEmpty($placeOrderResponse['placeOrder']['orderV2']['number']);
$this->assertNotEmpty($placeOrderResponse['placeOrder']['orderV2']['token']);
+ $this->assertNotEmpty($placeOrderResponse['placeOrder']['orderV2']['email']);
$this->assertNotEmpty($placeOrderResponse['placeOrder']['orderV2']['billing_address']['firstname']);
$this->assertNotEmpty($placeOrderResponse['placeOrder']['orderV2']['billing_address']['lastname']);
@@ -111,6 +114,7 @@ public function testGuestOrder(): void
[
'guestOrderByToken' => [
'number' => $placeOrderResponse['placeOrder']['orderV2']['number'],
+ 'email' => $placeOrderResponse['placeOrder']['orderV2']['email'],
'billing_address' => [
'firstname' => $placeOrderResponse['placeOrder']['orderV2']['billing_address']['firstname'],
'lastname' => $placeOrderResponse['placeOrder']['orderV2']['billing_address']['lastname']
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Sales/GuestOrderTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Sales/GuestOrderTest.php
index fe8a57d19a2..856defb108f 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Sales/GuestOrderTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Sales/GuestOrderTest.php
@@ -47,6 +47,7 @@ class GuestOrderTest extends GraphQlAbstract
postcode: "%postcode"
}) {
number
+ email
billing_address {
firstname
lastname
@@ -83,6 +84,7 @@ public function testGuestOrder(): void
[
'guestOrder' => [
'number' => $order->getIncrementId(),
+ 'email' => $order->getBillingAddress()->getEmail(),
'billing_address' => [
'firstname' => $order->getBillingAddress()->getFirstname(),
'lastname' => $order->getBillingAddress()->getLastname()
diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Tax/StoreConfigResolverTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Tax/StoreConfigResolverTest.php
index 9b8f2123198..0f2af31f786 100644
--- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Tax/StoreConfigResolverTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Tax/StoreConfigResolverTest.php
@@ -25,6 +25,7 @@ class StoreConfigResolverTest extends GraphQlAbstract
ConfigFixture(Config::XML_PATH_DISPLAY_CART_GRANDTOTAL, 1, ScopeInterface::SCOPE_STORE, 'default'),
ConfigFixture(Config::XML_PATH_DISPLAY_CART_FULL_SUMMARY, 1, ScopeInterface::SCOPE_STORE, 'default'),
ConfigFixture(Config::XML_PATH_DISPLAY_CART_ZERO_TAX, 1, ScopeInterface::SCOPE_STORE, 'default'),
+ ConfigFixture('tax/cart_display/gift_wrapping', 3, ScopeInterface::SCOPE_STORE, 'default'),
]
public function testGetStoreConfig(): void
{
@@ -38,6 +39,7 @@ public function testGetStoreConfig(): void
shopping_cart_display_grand_total,
shopping_cart_display_full_summary,
shopping_cart_display_zero_tax,
+ shopping_cart_display_tax_gift_wrapping,
}
}
QUERY;
@@ -60,5 +62,6 @@ private function validateStoreConfig(
$this->assertEquals(1, $responseConfig['shopping_cart_display_grand_total']);
$this->assertEquals(1, $responseConfig['shopping_cart_display_full_summary']);
$this->assertEquals(1, $responseConfig['shopping_cart_display_zero_tax']);
+ $this->assertEquals('DISPLAY_TYPE_BOTH', $responseConfig['shopping_cart_display_tax_gift_wrapping']);
}
}