const BasePage = require('./BasePage'); class LoginPage extends BasePage { constructor(driver) { super(driver); // Selectors based on the LoginForm component this.selectors = { form: '.login-form', heading: '.login-form h2', emailInput: '#email', passwordInput: '#password', submitButton: 'button[type="submit"]', errorMessage: '.error-message', generalError: '.alert-error', fieldError: '.error-message' }; } async navigateToLogin() { await this.navigateTo('/'); // Click the Login tab if not already active const loginButton = await this.driver.findElement({ css: '.auth-toggle button:first-child' }); await loginButton.click(); await this.waitForLoginForm(); } async waitForLoginForm() { await this.utils.waitForElementVisible(this.selectors.form); } async isLoginFormDisplayed() { return await this.isElementVisible(this.selectors.form); } async getLoginHeading() { return await this.getElementText(this.selectors.heading); } async enterEmail(email) { await this.typeIntoElement(this.selectors.emailInput, email); } async enterPassword(password) { await this.typeIntoElement(this.selectors.passwordInput, password); } async clickSubmit() { await this.clickElement(this.selectors.submitButton); } async getSubmitButtonText() { return await this.getElementText(this.selectors.submitButton); } async isSubmitButtonDisabled() { const button = await this.utils.waitForElement(this.selectors.submitButton); return await button.getAttribute('disabled') !== null; } async login(email, password) { await this.enterEmail(email); await this.enterPassword(password); await this.clickSubmit(); } async getGeneralErrorMessage() { try { return await this.getElementText(this.selectors.generalError); } catch (error) { return null; } } async getEmailErrorMessage() { try { const emailField = await this.utils.waitForElement(this.selectors.emailInput); const parent = await emailField.findElement({ xpath: '..' }); const errorElement = await parent.findElement({ css: this.selectors.fieldError }); return await errorElement.getText(); } catch (error) { return null; } } async getPasswordErrorMessage() { try { const passwordField = await this.utils.waitForElement(this.selectors.passwordInput); const parent = await passwordField.findElement({ xpath: '..' }); const errorElement = await parent.findElement({ css: this.selectors.fieldError }); return await errorElement.getText(); } catch (error) { return null; } } async hasEmailFieldError() { const emailField = await this.utils.waitForElement(this.selectors.emailInput); const className = await emailField.getAttribute('class'); return className.includes('error'); } async hasPasswordFieldError() { const passwordField = await this.utils.waitForElement(this.selectors.passwordInput); const className = await passwordField.getAttribute('class'); return className.includes('error'); } async waitForSuccessfulLogin() { // Wait for dashboard to appear (auth guard passes) await this.driver.wait( async () => { try { const dashboard = await this.driver.findElement({ css: '.dashboard' }); return await dashboard.isDisplayed(); } catch (error) { return false; } }, 10000, 'Login did not show dashboard within expected time' ); } async waitForLoginError() { // Wait for either general error or field errors to appear await this.driver.wait( async () => { const hasGeneralError = await this.isElementVisible(this.selectors.generalError); const hasEmailError = await this.hasEmailFieldError(); const hasPasswordError = await this.hasPasswordFieldError(); return hasGeneralError || hasEmailError || hasPasswordError; }, 10000, 'No error message appeared within expected time' ); } } module.exports = LoginPage;