Skip to content

Commit 1e6c6e0

Browse files
committed
Add GraphQL coverage for Reset password for MyAccount
1 parent e5ea17f commit 1e6c6e0

File tree

6 files changed

+535
-0
lines changed

6 files changed

+535
-0
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CustomerGraphQl\Model\Resolver;
9+
10+
use Magento\Customer\Api\AccountManagementInterface;
11+
use Magento\Customer\Model\AccountManagement;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\Framework\GraphQl\Config\Element\Field;
14+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
15+
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
16+
use Magento\Framework\GraphQl\Query\Resolver\Value;
17+
use Magento\Framework\GraphQl\Query\ResolverInterface;
18+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
19+
use Magento\Framework\Validator\EmailAddress as EmailValidator;
20+
21+
/**
22+
* Class Resolver for RequestPasswordResetEmail
23+
*/
24+
class RequestPasswordResetEmail implements ResolverInterface
25+
{
26+
/**
27+
* @var AccountManagementInterface
28+
*/
29+
private $customerAccountManagement;
30+
31+
/**
32+
* @var EmailValidator
33+
*/
34+
private $emailValidator;
35+
36+
/**
37+
* RequestPasswordResetEmail constructor.
38+
*
39+
* @param AccountManagementInterface $customerAccountManagement
40+
* @param EmailValidator $emailValidator
41+
*/
42+
public function __construct(
43+
AccountManagementInterface $customerAccountManagement,
44+
EmailValidator $emailValidator
45+
) {
46+
$this->customerAccountManagement = $customerAccountManagement;
47+
$this->emailValidator = $emailValidator;
48+
}
49+
50+
/**
51+
* Send password email request
52+
*
53+
* @param Field $field
54+
* @param ContextInterface $context
55+
* @param ResolveInfo $info
56+
* @param array|null $value
57+
* @param array|null $args
58+
*
59+
* @return bool|Value|mixed
60+
*
61+
* @throws GraphQlInputException
62+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
63+
*/
64+
public function resolve(
65+
Field $field,
66+
$context,
67+
ResolveInfo $info,
68+
array $value = null,
69+
array $args = null
70+
) {
71+
if (empty($args['email'])) {
72+
throw new GraphQlInputException(__('Email must be specified'));
73+
}
74+
75+
if (!$this->emailValidator->isValid($args['email'])) {
76+
throw new GraphQlInputException(__('Email is invalid'));
77+
}
78+
79+
try {
80+
return $this->customerAccountManagement->initiatePasswordReset(
81+
$args['email'],
82+
AccountManagement::EMAIL_RESET
83+
);
84+
} catch (LocalizedException $e) {
85+
throw new GraphQlInputException(__($e->getMessage()), $e);
86+
}
87+
}
88+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CustomerGraphQl\Model\Resolver;
9+
10+
use Magento\Customer\Api\AccountManagementInterface;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
14+
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
15+
use Magento\Framework\GraphQl\Query\Resolver\Value;
16+
use Magento\Framework\GraphQl\Query\ResolverInterface;
17+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
18+
use Magento\Framework\Validator\EmailAddress as EmailValidator;
19+
20+
class ResetPassword implements ResolverInterface
21+
{
22+
/**
23+
* @var AccountManagementInterface
24+
*/
25+
private $customerAccountManagement;
26+
27+
/**
28+
* @var EmailValidator
29+
*/
30+
private $emailValidator;
31+
32+
/**
33+
* RequestPasswordResetEmail constructor.
34+
*
35+
* @param AccountManagementInterface $customerAccountManagement
36+
* @param EmailValidator $emailValidator
37+
*/
38+
public function __construct(
39+
AccountManagementInterface $customerAccountManagement,
40+
EmailValidator $emailValidator
41+
) {
42+
$this->customerAccountManagement = $customerAccountManagement;
43+
$this->emailValidator = $emailValidator;
44+
}
45+
46+
/**
47+
* Reset old password and set new
48+
*
49+
* @param Field $field
50+
* @param ContextInterface $context
51+
* @param ResolveInfo $info
52+
* @param array|null $value
53+
* @param array|null $args
54+
*
55+
* @return bool|Value|mixed
56+
*
57+
* @throws GraphQlInputException
58+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
59+
*/
60+
public function resolve(
61+
Field $field,
62+
$context,
63+
ResolveInfo $info,
64+
array $value = null,
65+
array $args = null
66+
) {
67+
if (empty($args['email'])) {
68+
throw new GraphQlInputException(__('Email must be specified'));
69+
}
70+
71+
if (!$this->emailValidator->isValid($args['email'])) {
72+
throw new GraphQlInputException(__('Email is invalid'));
73+
}
74+
75+
if (empty($args['resetPasswordToken'])) {
76+
throw new GraphQlInputException(__('resetPasswordToken must be specified'));
77+
}
78+
79+
if (empty($args['newPassword'])) {
80+
throw new GraphQlInputException(__('newPassword must be specified'));
81+
}
82+
83+
try {
84+
return $this->customerAccountManagement->resetPassword(
85+
$args['email'],
86+
$args['resetPasswordToken'],
87+
$args['newPassword']
88+
);
89+
} catch (LocalizedException $e) {
90+
throw new GraphQlInputException(__($e->getMessage()), $e);
91+
}
92+
}
93+
}

app/code/Magento/CustomerGraphQl/etc/graphql/di.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,13 @@
2020
</argument>
2121
</arguments>
2222
</type>
23+
<type name="Magento\StoreGraphQl\Model\Resolver\Store\StoreConfigDataProvider">
24+
<arguments>
25+
<argument name="extendedConfigData" xsi:type="array">
26+
<item name="required_character_classes_number" xsi:type="string">customer/password/required_character_classes_number</item>
27+
<item name="minimum_password_length" xsi:type="string">customer/password/minimum_password_length</item>
28+
<item name="autocomplete_on_storefront" xsi:type="string">customer/password/autocomplete_on_storefront</item>
29+
</argument>
30+
</arguments>
31+
</type>
2332
</config>

app/code/Magento/CustomerGraphQl/etc/schema.graphqls

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
# Copyright © Magento, Inc. All rights reserved.
22
# See COPYING.txt for license details.
33

4+
type StoreConfig @doc(description: "The type contains information about a store config") {
5+
required_character_classes_number : String @doc(description: "Number of Required Character Classes")
6+
minimum_password_length : String @doc(description: "Minimum Password Length")
7+
autocomplete_on_storefront : Boolean @doc(description: "Enable Autocomplete on login or forgot password forms")
8+
}
9+
410
type Query {
511
customer: Customer @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\Customer") @doc(description: "The customer query returns information about a customer account") @cache(cacheable: false)
612
isEmailAvailable (
@@ -17,6 +23,8 @@ type Mutation {
1723
createCustomerAddress(input: CustomerAddressInput!): CustomerAddress @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\CreateCustomerAddress") @doc(description: "Create customer address")
1824
updateCustomerAddress(id: Int!, input: CustomerAddressInput): CustomerAddress @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\UpdateCustomerAddress") @doc(description: "Update customer address")
1925
deleteCustomerAddress(id: Int!): Boolean @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\DeleteCustomerAddress") @doc(description: "Delete customer address")
26+
requestPasswordResetEmail(email: String!): Boolean @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\RequestPasswordResetEmail") @doc(description: "Request an email with reset password token for the registered customer identified by the provided email")
27+
resetPassword(email: String!, resetPasswordToken: String!, newPassword: String!): Boolean @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\ResetPassword") @doc(description: "Reset customer password using reset password token received in the email after requesting it using requestPasswordResetEmail")
2028
}
2129

2230
input CustomerAddressInput {
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\GraphQl\Customer;
9+
10+
use Magento\TestFramework\TestCase\GraphQlAbstract;
11+
12+
class RequestPasswordResetEmailTest extends GraphQlAbstract
13+
{
14+
/**
15+
* @magentoApiDataFixture Magento/Customer/_files/customer.php
16+
*/
17+
public function testCustomerAccountWithEmailAvailable()
18+
{
19+
$query =
20+
<<<QUERY
21+
mutation {
22+
requestPasswordResetEmail(email: "[email protected]")
23+
}
24+
QUERY;
25+
$response = $this->graphQlMutation($query);
26+
27+
self::assertArrayHasKey('requestPasswordResetEmail', $response);
28+
self::assertTrue($response['requestPasswordResetEmail']);
29+
}
30+
31+
/**
32+
* Check if customer account is not available
33+
*/
34+
public function testCustomerAccountWithEmailNotAvailable()
35+
{
36+
$query =
37+
<<<QUERY
38+
mutation {
39+
requestPasswordResetEmail(email: "[email protected]")
40+
}
41+
QUERY;
42+
$this->assertMessage('No such entity with email = [email protected], websiteId = 1');
43+
$this->graphQlMutation($query);
44+
}
45+
46+
/**
47+
* Check if email value empty
48+
*/
49+
public function testEmailAvailableEmptyValue()
50+
{
51+
$query = <<<QUERY
52+
mutation {
53+
requestPasswordResetEmail(email: "")
54+
}
55+
QUERY;
56+
$this->assertMessage('Email must be specified');
57+
$this->graphQlMutation($query);
58+
}
59+
60+
/**
61+
* Check if email is invalid
62+
*/
63+
public function testEmailAvailableInvalidValue()
64+
{
65+
$query = <<<QUERY
66+
mutation {
67+
requestPasswordResetEmail(email: "invalid-email")
68+
}
69+
QUERY;
70+
$this->assertMessage('Email is invalid');
71+
$this->graphQlMutation($query);
72+
}
73+
74+
/**
75+
* Check if email contain right type
76+
*/
77+
public function testEmailAvailableTypeValue()
78+
{
79+
$query = <<<QUERY
80+
mutation {
81+
requestPasswordResetEmail (email: 12345)
82+
}
83+
QUERY;
84+
self::expectException(\Exception::class);
85+
self::expectExceptionMessage(
86+
'GraphQL response contains errors: Field "requestPasswordResetEmail" argument "email" requires type String!'
87+
);
88+
$this->graphQlMutation($query);
89+
}
90+
91+
/**
92+
* Checks Exception and ExceptionMessages
93+
*
94+
* @param $message
95+
*/
96+
private function assertMessage($message)
97+
{
98+
self::expectException(\Exception::class);
99+
self::expectExceptionMessage("GraphQL response contains errors: {$message}");
100+
}
101+
}

0 commit comments

Comments
 (0)