fix(accessibility): tab support at login, reset and signup pages, buttons at ATE and app bar (#24214)

Этот коммит содержится в:
Saturnino Abril
2023-08-10 08:53:13 -04:00
коммит произвёл GitHub
родитель 45a14e23a9
Коммит ecf7cdbdea
26 изменённых файлов: 441 добавлений и 87 удалений

Просмотреть файл

@@ -0,0 +1,30 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, Locator} from '@playwright/test';
export default class Footer {
readonly container: Locator;
readonly copyright;
readonly aboutLink;
readonly privacyPolicyLink;
readonly termsLink;
readonly helpLink;
constructor(container: Locator) {
this.container = container;
this.copyright = container.locator('.footer-copyright');
this.aboutLink = container.locator('text=About');
this.privacyPolicyLink = container.locator('text=Privacy Policy');
this.termsLink = container.locator('text=Terms');
this.helpLink = container.locator('text=Help');
}
async toBeVisible() {
await expect(this.copyright).toBeVisible();
}
}
export {Footer};

Просмотреть файл

@@ -10,7 +10,9 @@ import {ChannelsPost} from './channels/post';
import {ChannelsSidebarLeft} from './channels/sidebar_left';
import {ChannelsSidebarRight} from './channels/sidebar_right';
import {FindChannelsModal} from './channels/find_channels_modal';
import {Footer} from './footer';
import {GlobalHeader} from './global_header';
import {MainHeader} from './main_header';
import {PostDotMenu} from './channels/post_dot_menu';
import {DeletePostModal} from './channels/delete_post_modal';
import {PostMenu} from './channels/post_menu';
@@ -26,7 +28,9 @@ const components = {
ChannelsSidebarLeft,
ChannelsSidebarRight,
FindChannelsModal,
Footer,
GlobalHeader,
MainHeader,
PostDotMenu,
DeletePostModal,
PostMenu,

Просмотреть файл

@@ -0,0 +1,24 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, Locator} from '@playwright/test';
export default class MainHeader {
readonly container: Locator;
readonly logo;
readonly backButton;
constructor(container: Locator) {
this.container = container;
this.logo = container.locator('.header-logo-link');
this.backButton = container.getByTestId('back_button');
}
async toBeVisible() {
await expect(this.container).toBeVisible();
}
}
export {MainHeader};

Просмотреть файл

@@ -6,6 +6,7 @@ import {BoardsViewPage} from './boards_view';
import {ChannelsPage} from './channels';
import {LandingLoginPage} from './landing_login';
import {LoginPage} from './login';
import {ResetPasswordPage} from './reset_password';
import {SignupPage} from './signup';
const pages = {
@@ -14,6 +15,7 @@ const pages = {
ChannelsPage,
LandingLoginPage,
LoginPage,
ResetPasswordPage,
SignupPage,
};

Просмотреть файл

@@ -6,6 +6,8 @@ import {expect, Page} from '@playwright/test';
import {AdminConfig} from '@mattermost/types/config';
import {UserProfile} from '@mattermost/types/users';
import {components} from '@e2e-support/ui/components';
export default class LoginPage {
readonly adminConfig: AdminConfig;
@@ -17,6 +19,7 @@ export default class LoginPage {
readonly loginInput;
readonly loginPlaceholder;
readonly passwordInput;
readonly passwordToggleButton;
readonly signInButton;
readonly createAccountLink;
readonly forgotPasswordLink;
@@ -24,6 +27,9 @@ export default class LoginPage {
readonly fieldWithError;
readonly formContainer;
readonly header;
readonly footer;
constructor(page: Page, adminConfig: AdminConfig) {
this.page = page;
this.adminConfig = adminConfig;
@@ -34,16 +40,20 @@ export default class LoginPage {
this.title = page.locator('h1:has-text("Log in to your account")');
this.subtitle = page.locator('text=Collaborate with your team in real-time');
this.bodyCard = page.locator('.login-body-card');
this.bodyCard = page.locator('.login-body-card-content');
this.loginInput = page.locator('#input_loginId');
this.loginPlaceholder = page.locator(`[placeholder="${loginInputPlaceholder}"]`);
this.passwordInput = page.locator('#input_password-input');
this.passwordToggleButton = page.getByRole('button', {name: 'Show or hide password'});
this.signInButton = page.locator('button:has-text("Log in")');
this.createAccountLink = page.locator("text=Don't have an account?");
this.forgotPasswordLink = page.locator('text=Forgot your password?');
this.userErrorLabel = page.locator('text=Please enter your email or username');
this.fieldWithError = page.locator('.with-error');
this.formContainer = page.locator('.signup-team__container');
this.header = new components.MainHeader(page.locator('.hfroute-header'));
this.footer = new components.Footer(page.locator('.hfroute-footer'));
}
async toBeVisible() {

Просмотреть файл

@@ -0,0 +1,51 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, Page} from '@playwright/test';
import {components} from '@e2e-support/ui/components';
export default class ResetPasswordPage {
readonly page: Page;
readonly title;
readonly subtitle;
readonly emailInput;
readonly resetButton;
readonly formContainer;
readonly header;
readonly footer;
constructor(page: Page) {
this.page = page;
this.title = page.locator('h1:has-text("Password Reset")');
this.subtitle = page.locator('text=To reset your password, enter the email address you used to sign up');
this.emailInput = page.locator(`[placeholder="Email"]`);
this.resetButton = page.locator('#passwordResetButton');
this.formContainer = page.locator('.signup-team__container');
this.header = new components.MainHeader(page.locator('.signup-header'));
this.footer = new components.Footer(page.locator('#footer_section'));
}
async toBeVisible() {
await this.page.waitForLoadState('networkidle');
await expect(this.title).toBeVisible();
await expect(this.subtitle).toBeVisible();
await expect(this.emailInput).toBeVisible();
await expect(this.resetButton).toBeVisible();
}
async goto() {
await this.page.goto('/reset_password');
}
async reset(email: string) {
await this.emailInput.fill(email);
await Promise.all([this.page.waitForNavigation(), this.resetButton.click()]);
}
}
export {ResetPasswordPage};

Просмотреть файл

@@ -4,6 +4,7 @@
import {expect, Page} from '@playwright/test';
import {duration, wait} from '@e2e-support/util';
import {components} from '@e2e-support/ui/components';
export default class SignupPage {
readonly page: Page;
@@ -14,28 +15,50 @@ export default class SignupPage {
readonly emailInput;
readonly usernameInput;
readonly passwordInput;
readonly passwordToggleButton;
readonly newsLetterCheckBox;
readonly newsLetterPrivacyPolicyLink;
readonly newsLetterUnsubscribeLink;
readonly agreementTermsOfUseLink;
readonly agreementPrivacyPolicyLink;
readonly createAccountButton;
readonly loginLink;
readonly emailError;
readonly usernameError;
readonly passwordError;
readonly header;
readonly footer;
constructor(page: Page) {
this.page = page;
this.title = page.locator('h1:has-text("Lets get started")');
this.subtitle = page.locator('text=Create your Mattermost account to start collaborating with your team');
this.bodyCard = page.locator('.signup-body-card');
this.bodyCard = page.locator('.signup-body-card-content');
this.loginLink = page.locator('text=Log in');
this.emailInput = page.locator('#input_email');
this.usernameInput = page.locator('#input_name');
this.passwordInput = page.locator('#input_password-input');
this.passwordToggleButton = page.getByRole('button', {name: 'Show or hide password'});
this.createAccountButton = page.locator('button:has-text("Create Account")');
this.loginLink = page.locator('text=Click here to sign in.');
this.emailError = page.locator('text=Please enter a valid email address');
this.usernameError = page.locator(
'text=Usernames have to begin with a lowercase letter and be 3-22 characters long. You can use lowercase letters, numbers, periods, dashes, and underscores.'
);
this.passwordError = page.locator('text=Must be 5-64 characters long.');
const newsletterBlock = page.locator('.check-input');
this.newsLetterCheckBox = newsletterBlock.getByRole('checkbox', {name: 'newsletter checkbox'});
this.newsLetterPrivacyPolicyLink = newsletterBlock.locator('text=Privacy Policy');
this.newsLetterUnsubscribeLink = newsletterBlock.locator('text=unsubscribe');
const agreementBlock = page.locator('.signup-body-card-agreement');
this.agreementTermsOfUseLink = agreementBlock.locator('text=Terms of Use');
this.agreementPrivacyPolicyLink = agreementBlock.locator('text=Privacy Policy');
this.header = new components.MainHeader(page.locator('.hfroute-header'));
this.footer = new components.Footer(page.locator('.hfroute-footer'));
}
async toBeVisible() {
@@ -49,7 +72,7 @@ export default class SignupPage {
}
async goto() {
await this.page.goto('/signup_email');
await this.page.goto('/signup_user_complete');
}
async create(user: {email: string; username: string; password: string}, waitForRedirect = true) {