# Test info

- Name: Function change password tests >> PROFILE_005 - Verify màn change password function
- Location: /root/code/portal-automation-test/tests/profile/change-password.spec.ts:100:9

# Error details

```
Error: locator.fill: Test timeout of 240000ms exceeded.
Call log:
  - waiting for locator('//input[@name=\'email\']')

    at LoginPage.fillLoginInfo (/root/code/portal-automation-test/pom/login.page.ts:61:43)
    at LoginPage.login (/root/code/portal-automation-test/pom/login.page.ts:66:20)
    at /root/code/portal-automation-test/tests/profile/change-password.spec.ts:121:29
    at /root/code/portal-automation-test/tests/profile/change-password.spec.ts:118:9
```

# Page snapshot

```yaml
- complementary:
  - img
  - link "(Portal-Auto-Lawyer) Portal QA":
    - /url: /
    - paragraph: (Portal-Auto-Lawyer)
    - paragraph: Portal QA
  - list:
    - listitem:
      - link "Home":
        - /url: https://qa.loprx.com
        - img
        - text: Home
    - listitem:
      - link "Case":
        - /url: https://qa.loprx.com/cases
        - img
        - text: Case
    - listitem:
      - link "Request":
        - /url: https://qa.loprx.com/requests
        - img
        - text: Request
    - listitem:
      - link "Client":
        - /url: https://qa.loprx.com/clients
        - img
        - text: Client
    - listitem:
      - button "Business/Contact":
        - img
        - text: Business/Contact
    - listitem:
      - button "Inbox/Sent":
        - img
        - text: Inbox/Sent
    - listitem:
      - button "Settings":
        - img
        - text: Settings
  - list:
    - listitem:
      - link "Shared with me":
        - /url: https://qa.loprx.com/shared/requests
        - img
        - text: Shared with me
- banner:
  - button:
    - img
  - button:
    - img
  - img
  - text: Tri01 Duc shared some information about Test Request Letter of Protection. Find out what it says. 5 days ago
  - img
  - text: What did Tri01 Duc say? Their response to Test Request Letter of Protection is waiting. 5 days ago
  - img
  - text: Link Case First shared some information about New Case 123 Letter of Protection. Find out what it says. 1 week ago
  - img
  - text: What did Tri01 Duc say? Their response to Test Request Letter of Protection is waiting. 5 days ago
  - img
  - img
  - textbox "Search..."
  - img
  - img
  - paragraph: No notifications yet
  - paragraph: When you get notifications, they'll show up here
  - button "Refresh"
  - list:
    - listitem:
      - img
      - paragraph: Pause notifications...
      - list:
        - listitem: For 30 minutes
        - listitem: For 1 hour
        - listitem: For 2 hours
        - listitem: Until tomorrow
    - listitem:
      - img
    - listitem:
      - img
    - listitem:
      - img
    - listitem:
      - img
    - listitem:
      - img
    - listitem:
      - img
  - img
  - button:
    - img
  - button "4 Cart":
    - img
    - text: 4 Cart
  - text: Feedback
  - img
  - link "Open user menu":
    - /url: "#"
    - text: Minh
- text: Tips
- paragraph: Get things done fast! Choose from a variety of request options under the "Communication" section. Submit your needs quickly and easily.
- paragraph: The Monitor section below is your one-stop shop for tracking requests! See how your requests are progressing and get notified of their outcomes with ease.
- paragraph: Forget email attachments. Click "Request" on the left, create your request, upload & share. Give it a try!
- paragraph: Tired of hunting for important info? Pin it! Cases, requests, clients, businesses, contacts - keep everything you need readily available. Explore each section on the left navigation and see how pinning can personalize your workspace.
- heading "Communicate to others about" [level=2]
- list:
  - listitem:
    - link "Letter of Protection":
      - /url: /requests/create?type_id=10001
      - img
      - paragraph: Letter of Protection
  - listitem:
    - link "Medical Bill":
      - /url: /requests/create?type_id=10002
      - img
      - paragraph: Medical Bill
  - listitem:
    - link "Prescription":
      - /url: /requests/create?type_id=10003
      - img
      - paragraph: Prescription
  - listitem:
    - link "Affidavit":
      - /url: /requests/create?type_id=10004
      - img
      - paragraph: Affidavit
  - listitem:
    - img
    - paragraph: Others
    - list:
      - listitem:
        - link "Coordination":
          - /url: /requests/create?type_id=10006
      - listitem:
        - link "Transfer":
          - /url: /requests/create?type_id=10007
      - listitem:
        - link "Others":
          - /url: /requests/create?type_id=10005
- heading "Monitor and manage requests" [level=2]
- paragraph: Effectively manage requests and shared items by choosing a specific date to view all corresponding activity.
- paragraph: My Requests
- paragraph: All Requests
- listbox:
  - listitem:
    - text: All requests
    - img
- listbox:
  - listitem:
    - text: 01/01/2025 - 12/31/2025
    - img
- heading "Requests (By You/Team/External)" [level=2]
- link "5993 Letter of Protection":
  - /url: /requests-report?type=business&request_type_id=10001&created_from=01/01/2025&created_to=12/31/2025
  - img
  - heading "5993" [level=2]
  - paragraph: Letter of Protection
- link "10 Medical Bill":
  - /url: /requests-report?type=business&request_type_id=10002&created_from=01/01/2025&created_to=12/31/2025
  - img
  - heading "10" [level=2]
  - paragraph: Medical Bill
- link "3 Coordination":
  - /url: /requests-report?type=business&request_type_id=10006&created_from=01/01/2025&created_to=12/31/2025
  - img
  - heading "3" [level=2]
  - paragraph: Coordination
- link "2 Affidavit":
  - /url: /requests-report?type=business&request_type_id=10004&created_from=01/01/2025&created_to=12/31/2025
  - img
  - heading "2" [level=2]
  - paragraph: Affidavit
- link "1 Prescription":
  - /url: /requests-report?type=business&request_type_id=10003&created_from=01/01/2025&created_to=12/31/2025
  - img
  - heading "1" [level=2]
  - paragraph: Prescription
- img
- heading "0" [level=2]
- paragraph: Transfer
- img
- heading "0" [level=2]
- paragraph: Delivery
- img
- heading "0" [level=2]
- paragraph: Others
- button:
  - img
- listbox:
  - listitem:
    - img
    - text: Letter of Protection
    - img
- heading "Status" [level=2]
- img
- img: 6000 5000 4000 3000 2000 1000 0 5990 5991 0 0 2 Open In Progress On Hold Closed
- img
- text: Team Request
- img
- text: Shared With Team
- heading "Status Detail" [level=2]
- img
- img: 5989 2 5989 0 0 0 0 0 0 0 2 Inquiry Awaiting Preparing Verbal Approval On Hold Processed Provided Accepted Cancelled Declined 6000 5000 4000 3000 2000 1000 0
- img
- text: Team Request
- img
- text: Shared With Team
```

# Test source

```ts
   1 | import { Page } from "@playwright/test";
   2 | import { BasePage } from "./base.page";
   3 | import { DashboardPage } from "./dashboard.page";
   4 | import { ForgotPage } from "./authentication/forgot.page";
   5 |
   6 | export class LoginPage extends BasePage {
   7 |
   8 |     constructor(page: Page) {
   9 |         super(page)
  10 |     }
  11 |
  12 |     async open() {
  13 |         await this.page.goto('sign-in', { waitUntil: 'domcontentloaded' });
  14 |     }
  15 |
  16 |     get loginLoc() {
  17 |         return {
  18 |             // form
  19 |             mainContainer: this.genLoc("//div[./form]"),
  20 |             inputUsername: this.genLoc("//input[@name='email']"),
  21 |             inputPassword: this.genLoc("//input[@name='password']"),
  22 |             cbRemember: this.genLoc("//input[@name='remember']"),
  23 |             btnLogin: this.genLoc("//button[@type='submit' and normalize-space()='Log in']"),
  24 |             btnNext: this.genLoc("//button[text()='Next']"),
  25 |             forgotPasswordLink: this.genLoc("//a[contains(text(), 'Forgot Password')]"),
  26 |             loginWithPasscodeLink: this.genLoc("//a[contains(text(), 'Login with passcode')]"),
  27 |             eyeIcon: (status: string) => this.genLoc(`//a[@aria-label='${status} password']`),
  28 |             emailError: this.genLoc("//span[contains(text(), 'Enter an email.')]"),
  29 |             emailFormatError: this.genLoc("//span[contains(text(), 'Please enter a valid email address.')]"),
  30 |             passwordRequiredError: this.genLoc("//span[contains(text(), 'Enter a password.')]"),
  31 |             invalidCredentialError: this.genLoc("//span[contains(text(), 'These credentials do not match our records.')]"),
  32 |             infoButton: this.genLoc("//span[@role='button']"),
  33 |             trustedBrowserDialog: this.genLoc("//div[@class='modal-content']"),
  34 |             trustedBrowserTitle: this.genLoc("//h5[@class='modal-title']"),
  35 |             gotItButton: this.genLoc("//button[@type='button' and @class='btn-close']"),
  36 |
  37 |             // tos things
  38 |             tosLink: this.genLoc("//a[normalize-space()='Terms of Use']"),
  39 |             privacyPolicyLink: this.genLoc("//a[normalize-space()='Privacy Policy']"),
  40 |             baaLink: this.genLoc("//a[normalize-space()='Business Associate Agreement']"),
  41 |
  42 |             // 2FA
  43 |             twoFaLoginHeading: this.genLoc("//h2[normalize-space()='Two-factor authentication']"),
  44 |             digitInput: (digitNum: number) => this.genLoc(`//input[@id="digit-${digitNum}"]`),
  45 |             confirmButton: this.genLoc(`//button[@type='submit' and normalize-space()='Confirm']`),
  46 |
  47 |             // Passcode
  48 |             headingLoginWithPasscode: this.genLoc("//h3[normalize-space()='Sign In with OTP']"),
  49 |             errorEnterEmail: this.genLoc("//span[contains(text(), 'Enter an email.')]"),
  50 |             errorEnterEmailFormat: this.genLoc("//span[contains(text(), 'Please enter a valid email address.')]"),
  51 |             errorEmailNotFound: this.genLoc(`//span[contains(text(), "We're searching our records to find the account for")]`),
  52 |             messageEmailFound: this.genLoc(`//span[contains(text(), "Passcode for one-time access was sent to")]`),
  53 |             resendCode: this.genLoc(`//a[contains(text(), "Resend code, didn't get it or has expired")]`),
  54 |             errorTryAgainLater: this.genLoc("//span[contains(text(), 'Your request is processing')]"),
  55 |             inputToken: this.genLoc("//input[@name='token']"),
  56 |             errorInvalidPasscode: this.genLoc("//span[contains(text(), 'Passcode is invalid or has expired.')]"),
  57 |         }
  58 |     }
  59 |
  60 |     async fillLoginInfo(username: string, password: string) {
> 61 |         await this.loginLoc.inputUsername.fill(username);
     |                                           ^ Error: locator.fill: Test timeout of 240000ms exceeded.
  62 |         await this.loginLoc.inputPassword.fill(password);
  63 |     }
  64 |
  65 |     async login(username: string, password: string, remember: boolean = false) {
  66 |         await this.fillLoginInfo(username, password);
  67 |         if (remember) {
  68 |             await this.loginLoc.cbRemember.check();
  69 |         }
  70 |
  71 |         await this.loginLoc.btnLogin.click();
  72 |         return new DashboardPage(this.page);
  73 |     }
  74 |
  75 |     async clickForgotPassword() {
  76 |         await this.loginLoc.forgotPasswordLink.click();
  77 |         return new ForgotPage(this.page);
  78 |     }
  79 | }
```