Skip to content

Commit

Permalink
reset password test
Browse files Browse the repository at this point in the history
  • Loading branch information
wojteknowacki committed Nov 16, 2023
1 parent 8b7082c commit 6d46c29
Show file tree
Hide file tree
Showing 12 changed files with 235 additions and 11 deletions.
92 changes: 92 additions & 0 deletions .github/workflows/e2e-pool.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: E2E pool

on: [pull_request]

jobs:
instances:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Install dependencies
run: npm ci
- name: Retrieve instance
id: retrieve_instance
env:
SALEOR_CLI_ENV: staging
run: |
echo "Getting instance"...
npx saleor login --headless --token=${{ secrets.STAGING_API_TOKEN }}
NAME=$(node scripts/pick-e2e-instance.js | jq -r .name)
echo "POOL_NAME=$NAME" >> $GITHUB_OUTPUT
echo "POOL_INSTANCE=https://$NAME.staging.saleor.cloud" >> $GITHUB_OUTPUT
outputs:
pollIntance:
run-tests:
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
shard: [1/2, 2/2]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run tests
env:
API_URI: "${{ needs.instances.outputs.POOL_INSTANCE }}/graphql/"
API_URI: "${{ steps.retrieve_instance.outputs.POOL_INSTANCE }}/graphql/"
BASE_URL: "${{ steps.retrieve_instance.outputs.POOL_INSTANCE }}/dashboard/"
E2E_USER_NAME: ${{ secrets.CYPRESS_USER_NAME }}
E2E_USER_PASSWORD: ${{ secrets.CYPRESS_USER_PASSWORD }}
E2E_PERMISSIONS_USERS_PASSWORD: ${{ secrets.CYPRESS_PERMISSIONS_USERS_PASSWORD }}
run: |
echo "Running tests on: $API_URI"
echo "Base url $BASE_URL"
npx playwright test --shard ${{ matrix.shard }}
- name: Release instance
if: always()
run: node scripts/release-e2e-instance.js ${{ steps.retrieve_instance.outputs.POOL_NAME }}
- name: Upload blob report to GitHub Actions Artifacts
if: always()
uses: actions/upload-artifact@v3
with:
name: all-blob-reports
path: blob-report
retention-days: 1

merge-reports:
if: always()
needs: [run-tests]

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Install dependencies
run: npm ci

- name: Download blob reports from GitHub Actions Artifacts
uses: actions/download-artifact@v3
with:
name: all-blob-reports
path: all-blob-reports

- name: Merge into HTML Report
run: npx playwright merge-reports --reporter html ./all-blob-reports

- name: Upload HTML report
uses: actions/upload-artifact@v3
with:
name: html-report--attempt-${{ github.run_attempt }}
path: playwright-report
retention-days: 14
2 changes: 1 addition & 1 deletion cypress/e2e/staffMembers.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ describe("Staff members", () => {
);

it(
"should not be able to create staff member with not unique email. TC: SALEOR_3508",
"should not be able to create staff member with not unique email. TC: SALEOR_3508 - should not be migrated to playwright as critical",
{ tags: ["@staffMembers", "@allEnv", "@critical"] },
() => {
const firstName = faker.name.firstName();
Expand Down
12 changes: 12 additions & 0 deletions playwright/api/mailpit.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { URL_LIST } from "@data/url";
import { APIRequestContext, expect } from "@playwright/test";

const MAILPIT_URI = process.env.CYPRESS_MAILPITURL || "no mailpit url provided";
Expand Down Expand Up @@ -51,4 +52,15 @@ export class MailpitService {

return userEmails;
}

async generateResetPasswordUrl(userEmail: string) {
const tokenRegex = /token=([A-Za-z0-9]+(-[A-Za-z0-9]+)+)/;

const userEmails = await this.getEmailsForUser(userEmail);
const emailDetails = await this.getEmailDetails(userEmails[0].ID);
const emailHtmlFormat = tokenRegex.exec(emailDetails.HTML.toString());
const token = "&" + emailHtmlFormat![0];
const resetPasswordUrl = URL_LIST.resetPassword + userEmail + token;
return resetPasswordUrl;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,11 @@ export const USERS = {
email: "[email protected]",
info: "Inactive user used in activation user test",
},
userForPasswordReset: {
email: "[email protected]",
newPassword: "4321test",
info: "User used in reset password test",
name: "e2e",
lastName: "user",
},
};
1 change: 1 addition & 0 deletions playwright/data/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ export const URL_LIST = {
variant: "variant/",
warehouses: "warehouses/",
webhooksAndEvents: "custom-apps/",
resetPassword: "/new-password/?email=",
};
16 changes: 16 additions & 0 deletions playwright/pages/loginPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,29 @@ export class LoginPage {
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly signInButton: Locator;
readonly resetPasswordLink: Locator;
readonly sendEmailWithResetLinkButton: Locator;
readonly backToLoginPageButton: Locator;
homePage: HomePage;
constructor(page: Page) {
this.page = page;
this.homePage = new HomePage(page);
this.emailInput = page.getByTestId("email");
this.passwordInput = page.getByTestId("password");
this.signInButton = page.getByTestId("submit");
this.resetPasswordLink = page.getByTestId("reset-password-link");
this.sendEmailWithResetLinkButton = page.getByTestId("submit");
this.backToLoginPageButton = page.getByTestId("back-to-login-button");
}

async clickBackToLoginPageButton() {
await this.backToLoginPageButton.click();
}
async clickResetPasswordLink() {
await this.resetPasswordLink.click();
}
async clickSendEmailWithResetLinkButton() {
await this.sendEmailWithResetLinkButton.click();
}

async loginAndSetStorageState(
Expand Down
34 changes: 34 additions & 0 deletions playwright/pages/setUpNewPasswordPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { MailpitService } from "@api/mailpit";
import type { APIRequestContext, Locator, Page } from "@playwright/test";

export class SetUpNewPasswordPage {
readonly page: Page;
readonly passwordInput: Locator;
readonly confirmPasswordInput: Locator;
readonly setNewPasswordButton: Locator;
readonly mailpitService: MailpitService;

constructor(page: Page, request: APIRequestContext) {
this.page = page;
this.mailpitService = new MailpitService(request);
this.passwordInput = page.getByTestId("password");
this.confirmPasswordInput = page.getByTestId("confirm-password");
this.setNewPasswordButton = page.getByTestId("button-bar-confirm");
}

async typePassword(password: string) {
await this.passwordInput.fill(password);
}
async typeConfirmedPassword(password: string) {
await this.confirmPasswordInput.fill(password);
}
async clickSetNewPasswordButton() {
await this.setNewPasswordButton.click();
}

async gotoUserResetPasswordPage(userEmail: string) {
const resetPasswordPageUrl =
await this.mailpitService.generateResetPasswordUrl(userEmail);
await this.page.goto(resetPasswordPageUrl);
}
}
25 changes: 18 additions & 7 deletions playwright/tests/auth.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,26 @@ const contentPermissionsFile = "playwright/.auth/content.json";
const channelsWebhooksPermissionsFile =
"playwright/.auth/channels-webhooks.json";
const customerWebhooksPermissionsFile = "playwright/.auth/customer.json";
const unauthenticatedUserPermissionsFile =
"playwright/.auth/unauthenticated-user.json";

setup("authenticate as admin", async ({ page }) => {
// setup("authenticate as admin", async ({ page }) => {
// const loginPage = await new LoginPage(page);
// await loginPage.loginAndSetStorageState(
// process.env.CYPRESS_USER_NAME!,
// process.env.CYPRESS_USER_PASSWORD!,
// page,
// adminFile,
// );
// });
setup("unauthenticated user ", async ({ page }) => {
const loginPage = await new LoginPage(page);
await loginPage.loginAndSetStorageState(
process.env.CYPRESS_USER_NAME!,
process.env.CYPRESS_USER_PASSWORD!,
page,
adminFile,
);
await loginPage.goto();
await loginPage.resetPasswordLink.waitFor({ state: "visible" });
// End of authentication steps.
await page
.context()
.storageState({ path: unauthenticatedUserPermissionsFile });
});
// setup("authenticate as user with discount permissions", async ({ page }) => {
// const loginPage = new LoginPage(page);
Expand Down
2 changes: 1 addition & 1 deletion playwright/tests/product.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PRODUCTS } from "@data/testData";
import { PRODUCTS } from "@data/e2eTestData";
import { BasePage } from "@pages/basePage";
import { ProductCreateDialog } from "@pages/dialogs/productCreateDialog";
import { ProductPage } from "@pages/productPage";
Expand Down
2 changes: 1 addition & 1 deletion playwright/tests/shippingMethods.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SHIPPING_METHODS } from "@data/testData";
import { SHIPPING_METHODS } from "@data/e2eTestData";
import { ShippingMethodsPage } from "@pages/shippingMethodsPage";
import { ShippingRatesPage } from "@pages/shippingRatesPage";
import { expect, test } from "@playwright/test";
Expand Down
52 changes: 51 additions & 1 deletion playwright/tests/staffMembers.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { BasicApiService } from "@api/basics";
import { USERS } from "@data/testData";
import { USERS } from "@data/e2eTestData";
import { URL_LIST } from "@data/url";
import { ConfigurationPage } from "@pages/configurationPage";
import { HomePage } from "@pages/homePage";
import { LoginPage } from "@pages/loginPage";
import { SetUpNewPasswordPage } from "@pages/setUpNewPasswordPage";
import { StaffMembersPage } from "@pages/staffMembersPage";
import { expect, test } from "@playwright/test";

Expand Down Expand Up @@ -97,3 +100,50 @@ test("TC: SALEOR_38 Admin User should be able to activate other user @basic-regr
loginViaApiDeactivatedUserResponse.data.tokenCreate.token,
).not.toEqual(null);
});

test.use({ storageState: "playwright/.auth/unauthenticated-user.json" });

test("TC: SALEOR_39 User should be able to reset password @basic-regression @staff-members", async ({
page,
request,
}) => {
const loginPage = new LoginPage(page);
const homePage = new HomePage(page);
const setUpNewPasswordPage = new SetUpNewPasswordPage(page, request);
const basicApiService = new BasicApiService(request);

await page.goto("/");
await loginPage.clickResetPasswordLink();
await loginPage.typeEmail(USERS.userForPasswordReset.email);
await loginPage.clickSendEmailWithResetLinkButton();
await loginPage.clickBackToLoginPageButton();
await loginPage.emailInput.waitFor({ state: "visible" });

await setUpNewPasswordPage.gotoUserResetPasswordPage(
USERS.userForPasswordReset.email,
);

await setUpNewPasswordPage.typePassword(
USERS.userForPasswordReset.newPassword,
);
await setUpNewPasswordPage.typeConfirmedPassword(
USERS.userForPasswordReset.newPassword,
);
await setUpNewPasswordPage.clickSetNewPasswordButton();
await expect(homePage.welcomeMessage).toBeVisible({ timeout: 10000 });
await expect(homePage.welcomeMessage).toContainText(
`${USERS.userForPasswordReset.name} ${USERS.userForPasswordReset.lastName}`,
);

const userWithNewPasswordLoginResponse =
await basicApiService.logInUserViaApi({
email: USERS.userForPasswordReset.email,
password: USERS.userForPasswordReset.newPassword,
});
await expect(
userWithNewPasswordLoginResponse.data.tokenCreate.errors,
).toEqual([]);
await expect(
userWithNewPasswordLoginResponse.data.tokenCreate.token,
).not.toEqual(null);
});
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const ResetPasswordSuccessPage: React.FC<
variant="primary"
onClick={onBack}
type="submit"
data-test-id="back-to-login-button"
>
<FormattedMessage
id="2oyWT9"
Expand Down

0 comments on commit 6d46c29

Please sign in to comment.