Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API][Account] Password change feature #11968

Closed
12 changes: 9 additions & 3 deletions features/account/customer_account/changing_password.feature
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ Feature: Changing a customer password

Background:
Given the store operates on a single channel in "United States"
And there is a customer "Francis Underwood" identified by an email "francis@underwood.com" and a password "whitehouse"
And there is a customer "Francis Underwood" identified by an email "francis@underwood.com" and a password "sylius"
And I am logged in as "francis@underwood.com"

@ui
@ui @api
Scenario: Changing my password
When I want to change my password
And I change password from "whitehouse" to "blackhouse"
And I change password from "sylius" to "blackhouse"
And I save my changes
Then I should be notified that my password has been successfully changed

@api @ui
Scenario: Logging to store after password change
Given I've changed my password from "whitehouse" to "blackhouse"
When I log in as "francis@underwood.com" with "blackhouse" password
Then I should be logged in
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ Feature: Customer password validation

Background:
Given the store operates on a single channel in "United States"
And there is a customer account "francis@underwood.com" identified by "whitehouse"
And there is a customer account "francis@underwood.com" identified by "sylius"
And I am logged in as "francis@underwood.com"

@ui
@ui @api
Scenario: Trying to change my password with a wrong current password
When I want to change my password
And I specify the current password as "greenhouse"
Expand All @@ -18,19 +18,19 @@ Feature: Customer password validation
And I try to save my changes
Then I should be notified that provided password is different than the current one

@ui
Scenario: Trying to change my password with a wrong confirmation password2
@ui @api
Scenario: Trying to change my password with a wrong confirmation password
When I want to change my password
And I specify the current password as "whitehouse"
And I specify the current password as "sylius"
And I specify the new password as "blackhouse"
And I confirm this password as "greenhouse"
And I try to save my changes
Then I should be notified that the entered passwords do not match

@ui
@ui @api
Scenario: Trying to change my password with a too short password
When I want to change my password
And I specify the current password as "whitehouse"
And I specify the current password as "sylius"
And I specify the new password as "fu"
And I confirm this password as "fu"
And I try to save my changes
Expand Down
5 changes: 5 additions & 0 deletions src/Sylius/Behat/Client/ApiPlatformClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ public function buildUpdateRequest(string $id): void
$this->request->setContent(json_decode($this->client->getResponse()->getContent(), true));
}

public function buildCustomUpdateRequest(string $id, string $customSuffix): void
{
$this->request = Request::update($this->section, $this->resource, sprintf('%s/%s', $id, $customSuffix), $this->getToken());
}

public function buildUploadRequest(): void
{
$this->request = Request::upload($this->section, $this->resource, $this->getToken());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Context\Setup\ShopSecurityContext;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Symfony\Component\HttpFoundation\Response;
use Webmozart\Assert\Assert;

final class AccountContext implements Context
final class CustomerContext implements Context
{
/** @var ApiClientInterface */
private $accountClient;
private $customerClient;

/** @var ApiClientInterface */
private $orderShopClient;
Expand All @@ -47,15 +47,15 @@ final class AccountContext implements Context
private $shopApiSecurityContext;

public function __construct(
ApiClientInterface $accountClient,
ApiClientInterface $customerClient,
ApiClientInterface $orderShopClient,
SharedStorageInterface $sharedStorage,
ResponseCheckerInterface $responseChecker,
RegistrationContext $registrationContext,
LoginContext $loginContext,
ShopSecurityContext $shopApiSecurityContext
) {
$this->accountClient = $accountClient;
$this->customerClient = $customerClient;
$this->orderShopClient = $orderShopClient;
$this->sharedStorage = $sharedStorage;
$this->responseChecker = $responseChecker;
Expand All @@ -73,7 +73,20 @@ public function iWantToModifyMyProfile(): void
$shopUser = $this->sharedStorage->get('user');
$customer = $shopUser->getCustomer();

$this->accountClient->buildUpdateRequest((string) $customer->getId());
$this->customerClient->buildUpdateRequest((string) $customer->getId());
}

/**
* @When I want to change my password
*/
public function iWantToChangeMyPassword(): void
{
/** @var ShopUserInterface $shopUser */
$shopUser = $this->sharedStorage->get('user');
/** @var CustomerInterface $customer */
$customer = $shopUser->getCustomer();

$this->customerClient->buildCustomUpdateRequest((string) $customer->getId(), 'password');
}

/**
Expand All @@ -82,7 +95,7 @@ public function iWantToModifyMyProfile(): void
*/
public function iSpecifyTheFirstName(string $firstName = ''): void
{
$this->accountClient->addRequestData('firstName', $firstName);
$this->customerClient->addRequestData('firstName', $firstName);
}

/**
Expand All @@ -91,7 +104,7 @@ public function iSpecifyTheFirstName(string $firstName = ''): void
*/
public function iSpecifyTheLastName(string $lastName = ''): void
{
$this->accountClient->addRequestData('lastName', $lastName);
$this->customerClient->addRequestData('lastName', $lastName);
}

/**
Expand All @@ -100,7 +113,7 @@ public function iSpecifyTheLastName(string $lastName = ''): void
*/
public function iSpecifyCustomerTheEmail(string $email = ''): void
{
$this->accountClient->addRequestData('email', $email);
$this->customerClient->addRequestData('email', $email);
}

/**
Expand All @@ -109,15 +122,51 @@ public function iSpecifyCustomerTheEmail(string $email = ''): void
*/
public function iSaveMyChanges(): void
{
$this->accountClient->update();
$this->customerClient->update();
}

/**
* @When I specify the current password as :password
*/
public function iSpecifyTheCurrentPasswordAs(string $password): void
{
$this->customerClient->addRequestData('currentPassword', $password);
}

/**
* @When I specify the new password as :password
*/
public function iSpecifyTheNewPasswordAs(string $password): void
{
$this->customerClient->addRequestData('newPassword', $password);
}

/**
* @When I confirm this password as :password
*/
public function iSpecifyTheConfirmationPasswordAs(string $password): void
{
$this->customerClient->addRequestData('confirmNewPassword', $password);
}

/**
* @When I change password from :oldPassword to :newPassword
*/
public function iChangePasswordTo(string $oldPassword, string $newPassword): void
{
$this->customerClient->setRequestData([
'currentPassword' => $oldPassword,
'newPassword' => $newPassword,
'confirmNewPassword' => $newPassword
]);
}

/**
* @Then I should be notified that it has been successfully edited
*/
public function iShouldBeNotifiedThatItHasBeenSuccessfullyEdited(): void
{
Assert::true($this->responseChecker->isUpdateSuccessful($this->accountClient->getLastResponse()));
Assert::true($this->responseChecker->isUpdateSuccessful($this->customerClient->getLastResponse()));
}

/**
Expand All @@ -131,7 +180,7 @@ public function myEmailShouldBe(string $email): void

$this->shopApiSecurityContext->iAmLoggedInAs($email);

$response = $this->accountClient->show((string) $shopUser->getCustomer()->getId());
$response = $this->customerClient->show((string) $shopUser->getCustomer()->getId());

Assert::true($this->responseChecker->hasValue($response, 'email', $email));
}
Expand All @@ -145,7 +194,7 @@ public function myNameShouldBe(string $name): void
/** @var ShopUserInterface $shopUser */
$shopUser = $this->sharedStorage->get('user');

$response = $this->accountClient->show((string) $shopUser->getCustomer()->getId());
$response = $this->customerClient->show((string) $shopUser->getCustomer()->getId());

Assert::true($this->responseChecker->hasValue($response, 'fullName', $name));
}
Expand All @@ -156,7 +205,7 @@ public function myNameShouldBe(string $name): void
public function iShouldBeNotifiedThatFirstNameIsRequired(): void
{
$this->isViolationWithMessageInResponse(
$this->accountClient->getLastResponse(),
$this->customerClient->getLastResponse(),
'First name must be at least 2 characters long.'
);
}
Expand All @@ -167,7 +216,7 @@ public function iShouldBeNotifiedThatFirstNameIsRequired(): void
public function iShouldBeNotifiedThatLastNameIsRequired(): void
{
$this->isViolationWithMessageInResponse(
$this->accountClient->getLastResponse(),
$this->customerClient->getLastResponse(),
'Last name must be at least 2 characters long.'
);
}
Expand All @@ -178,7 +227,7 @@ public function iShouldBeNotifiedThatLastNameIsRequired(): void
public function iShouldBeNotifiedThatEmailIsRequired(): void
{
$this->isViolationWithMessageInResponse(
$this->accountClient->getLastResponse(),
$this->customerClient->getLastResponse(),
'Please enter your email.'
);
}
Expand All @@ -189,7 +238,7 @@ public function iShouldBeNotifiedThatEmailIsRequired(): void
public function iShouldBeNotifiedThatTheEmailIsAlreadyUsed(): void
{
$this->isViolationWithMessageInResponse(
$this->accountClient->getLastResponse(),
$this->customerClient->getLastResponse(),
'This email is already used.'
);
}
Expand All @@ -200,7 +249,7 @@ public function iShouldBeNotifiedThatTheEmailIsAlreadyUsed(): void
public function iShouldBeNotifiedThatElementIsInvalid(): void
{
$this->isViolationWithMessageInResponse(
$this->accountClient->getLastResponse(),
$this->customerClient->getLastResponse(),
'This email is invalid.'
);
}
Expand Down Expand Up @@ -258,4 +307,54 @@ private function isViolationWithMessageInResponse(Response $response, string $me

return false;
}

/**
* @Then I should be notified that my password has been successfully changed
*/
public function iShouldBeNotifiedThatItHasBeenSuccessfullyChanged(): void
{
$response = $this->customerClient->getLastResponse();

Assert::same(
$response->getStatusCode(),
204,
$response->getContent()
);
}

/**
* @Then I should be notified that provided password is different than the current one
*/
public function iShouldBeNotifiedThatProvidedPasswordIsDifferentThanTheCurrentOne(): void
{
Assert::same($this->customerClient->getLastResponse()->getStatusCode(), 400);

Assert::contains(
$this->responseChecker->getError($this->customerClient->getLastResponse()),
'Provided password is different than the current one.'
);
}

/**
* @Then I should be notified that the entered passwords do not match
*/
public function iShouldBeNotifiedThatTheEnteredPasswordsDoNotMatch(): void
{
Assert::same($this->customerClient->getLastResponse()->getStatusCode(), 400);

Assert::contains(
$this->responseChecker->getError($this->customerClient->getLastResponse()),
'newPassword: The entered passwords don\'t match'
);
}

/**
* @Then /^I should be notified that the ([^"]+) should be ([^"]+)$/
*/
public function iShouldBeNotifiedThatTheElementShouldBe(string $elementName, string $validationMessage): void
{
Assert::contains($this->responseChecker->getError($this->customerClient->getLastResponse()),
sprintf('%s must be %s.', ucfirst($elementName), $validationMessage)
);
}
}
22 changes: 21 additions & 1 deletion src/Sylius/Behat/Context/Setup/UserContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@

namespace Sylius\Behat\Context\Setup;

use Behat\Behat\Tester\Exception\PendingException;
use Behat\Behat\Context\Context;
use Doctrine\Common\Persistence\ObjectManager;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Bundle\ApiBundle\Command\ChangeShopUserPassword;
use Sylius\Bundle\CoreBundle\Fixture\Factory\ExampleFactoryInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\User\Model\UserInterface;
use Sylius\Component\User\Repository\UserRepositoryInterface;
use Symfony\Component\Messenger\MessageBusInterface;

final class UserContext implements Context
{
Expand All @@ -35,16 +38,21 @@ final class UserContext implements Context
/** @var ObjectManager */
private $userManager;

/** @var MessageBusInterface */
private $messageBus;

public function __construct(
SharedStorageInterface $sharedStorage,
UserRepositoryInterface $userRepository,
ExampleFactoryInterface $userFactory,
ObjectManager $userManager
ObjectManager $userManager,
MessageBusInterface $messageBus
) {
$this->sharedStorage = $sharedStorage;
$this->userRepository = $userRepository;
$this->userFactory = $userFactory;
$this->userManager = $userManager;
$this->messageBus = $messageBus;
}

/**
Expand Down Expand Up @@ -166,4 +174,16 @@ private function prepareUserPasswordResetToken(UserInterface $user): void

$this->userManager->flush();
}

/**
* @Given /^(I)'ve changed my password from "([^"]+)" to "([^"]+)"$/
*/
public function iveChangedMyPasswordFromTo(UserInterface $user, string $currentPassword, string $newPassword): void
{
$changeShopUserPassword = new ChangeShopUserPassword($newPassword, $newPassword, $currentPassword);

$changeShopUserPassword->setShopUserId($user->getId());

$this->messageBus->dispatch($changeShopUserPassword);
}
}
Loading