Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s
219 lines
6.7 KiB
TypeScript
219 lines
6.7 KiB
TypeScript
import { type Locator, type Page } from '@playwright/test';
|
|
|
|
export class LoginPage {
|
|
private readonly loginWithGoogleButton: Locator;
|
|
private readonly loginWithEmailButton: Locator;
|
|
private readonly termsOfServiceLink: Locator;
|
|
private readonly privacyPolicyLink: Locator;
|
|
private readonly emailField: Locator;
|
|
private readonly continueButton: Locator;
|
|
private readonly forgotPasswordButton: Locator;
|
|
private readonly passwordField: Locator;
|
|
private readonly revealPasswordButton: Locator;
|
|
readonly signInButton: Locator;
|
|
private readonly signUpButton: Locator;
|
|
private readonly previewImageButton: Locator;
|
|
private readonly uploadImageButton: Locator;
|
|
private readonly deleteImageButton: Locator;
|
|
private readonly workspaceNameField: Locator;
|
|
private readonly subdomainField: Locator;
|
|
private readonly createWorkspaceButton: Locator;
|
|
private readonly skipOnboardingStepButton: Locator;
|
|
private readonly firstNameField: Locator;
|
|
private readonly lastNameField: Locator;
|
|
private readonly syncEverythingWithGoogleRadio: Locator;
|
|
private readonly syncSubjectAndMetadataWithGoogleRadio: Locator;
|
|
private readonly syncMetadataWithGoogleRadio: Locator;
|
|
private readonly syncWithGoogleButton: Locator;
|
|
private readonly noSyncButton: Locator;
|
|
private readonly inviteLinkField1: Locator;
|
|
private readonly inviteLinkField2: Locator;
|
|
private readonly inviteLinkField3: Locator;
|
|
private readonly copyInviteLink: Locator;
|
|
private readonly finishButton: Locator;
|
|
|
|
constructor(public readonly page: Page) {
|
|
this.page = page;
|
|
this.loginWithGoogleButton = page.getByRole('button', {
|
|
name: 'Continue with Google',
|
|
});
|
|
this.loginWithEmailButton = page.getByRole('button', {
|
|
name: 'Continue with Email',
|
|
});
|
|
this.termsOfServiceLink = page.getByRole('link', {
|
|
name: 'Terms of Service',
|
|
});
|
|
this.privacyPolicyLink = page.getByRole('link', { name: 'Privacy Policy' });
|
|
this.emailField = page.getByPlaceholder('Email');
|
|
this.continueButton = page.getByRole('button', {
|
|
name: 'Continue',
|
|
exact: true,
|
|
});
|
|
this.forgotPasswordButton = page.getByText('Forgot your password?');
|
|
this.passwordField = page.getByPlaceholder('Password');
|
|
this.revealPasswordButton = page.getByTestId('reveal-password-button');
|
|
this.signInButton = page.getByRole('button', { name: 'Sign in' });
|
|
this.signUpButton = page.getByRole('button', { name: 'Sign up' });
|
|
this.previewImageButton = page.locator('.css-1qzw107'); // TODO: fix
|
|
this.uploadImageButton = page.getByRole('button', { name: 'Upload' });
|
|
this.deleteImageButton = page.getByRole('button', { name: 'Remove' });
|
|
this.workspaceNameField = page.getByLabel('Name', { exact: true });
|
|
this.subdomainField = page.getByLabel('Subdomain', { exact: true });
|
|
this.createWorkspaceButton = page.getByRole('button', {
|
|
name: 'Create workspace',
|
|
});
|
|
this.skipOnboardingStepButton = page.getByRole('button', {
|
|
name: 'Skip',
|
|
exact: true,
|
|
});
|
|
this.firstNameField = page.getByLabel('First Name', { exact: true });
|
|
this.lastNameField = page.getByLabel('Last name', { exact: true });
|
|
this.syncEverythingWithGoogleRadio = page.locator(
|
|
'input[value="SHARE_EVERYTHING"]',
|
|
);
|
|
this.syncSubjectAndMetadataWithGoogleRadio = page.locator(
|
|
'input[value="SUBJECT"]',
|
|
);
|
|
this.syncMetadataWithGoogleRadio = page.locator('input[value="METADATA"]');
|
|
this.syncWithGoogleButton = page.getByRole('button', {
|
|
name: 'Sync with Google',
|
|
});
|
|
this.noSyncButton = page.getByText('Continue without sync');
|
|
this.inviteLinkField1 = page.getByPlaceholder('tim@apple.dev');
|
|
this.inviteLinkField2 = page.getByPlaceholder('craig@apple.dev');
|
|
this.inviteLinkField3 = page.getByPlaceholder('mike@apple.dev');
|
|
this.copyInviteLink = page.getByRole('button', {
|
|
name: 'Copy invitation link',
|
|
});
|
|
this.finishButton = page.getByRole('button', { name: 'Finish' });
|
|
}
|
|
|
|
async loginWithGoogle() {
|
|
await this.loginWithGoogleButton.click();
|
|
}
|
|
|
|
async clickLoginWithEmail() {
|
|
await this.loginWithEmailButton.click();
|
|
}
|
|
|
|
async clickLoginWithEmailIfVisible() {
|
|
try {
|
|
await this.loginWithEmailButton.click({ timeout: 3000 });
|
|
} catch {
|
|
// Button not found - email field might already be visible (SSO-only or different auth flow)
|
|
}
|
|
}
|
|
|
|
async clickContinueButton() {
|
|
await this.continueButton.click();
|
|
}
|
|
|
|
async clickTermsLink() {
|
|
await this.termsOfServiceLink.click();
|
|
}
|
|
|
|
async clickPrivacyPolicyLink() {
|
|
await this.privacyPolicyLink.click();
|
|
}
|
|
|
|
async typeEmail(email: string) {
|
|
await this.emailField.fill(email, { timeout: 30000 });
|
|
}
|
|
|
|
async typePassword(email: string) {
|
|
await this.passwordField.fill(email);
|
|
}
|
|
|
|
async clickSignInButton() {
|
|
await this.signInButton.click();
|
|
}
|
|
|
|
async clickSignUpButton() {
|
|
await this.signUpButton.click();
|
|
}
|
|
|
|
async clickForgotPassword() {
|
|
await this.forgotPasswordButton.click();
|
|
}
|
|
|
|
async revealPassword() {
|
|
await this.revealPasswordButton.click();
|
|
}
|
|
|
|
async previewImage() {
|
|
await this.previewImageButton.click();
|
|
}
|
|
|
|
async clickUploadImage() {
|
|
await this.uploadImageButton.click();
|
|
}
|
|
|
|
async deleteImage() {
|
|
await this.deleteImageButton.click();
|
|
}
|
|
|
|
async typeWorkspaceName(workspaceName: string) {
|
|
await this.workspaceNameField.fill(workspaceName);
|
|
}
|
|
|
|
async typeSubdomain(subdomain: string) {
|
|
await this.subdomainField.fill(subdomain);
|
|
}
|
|
|
|
async clickCreateWorkspaceButton() {
|
|
await this.createWorkspaceButton.click();
|
|
}
|
|
|
|
async clickSkipOnboardingStep() {
|
|
await this.skipOnboardingStepButton.click();
|
|
}
|
|
|
|
async typeFirstName(firstName: string) {
|
|
await this.firstNameField.fill(firstName);
|
|
}
|
|
|
|
async typeLastName(lastName: string) {
|
|
await this.lastNameField.fill(lastName);
|
|
}
|
|
|
|
async clickSyncEverythingWithGoogleRadio() {
|
|
await this.syncEverythingWithGoogleRadio.click();
|
|
}
|
|
|
|
async clickSyncSubjectAndMetadataWithGoogleRadio() {
|
|
await this.syncSubjectAndMetadataWithGoogleRadio.click();
|
|
}
|
|
|
|
async clickSyncMetadataWithGoogleRadio() {
|
|
await this.syncMetadataWithGoogleRadio.click();
|
|
}
|
|
|
|
async clickSyncWithGoogleButton() {
|
|
await this.syncWithGoogleButton.click();
|
|
}
|
|
|
|
async noSyncWithGoogle() {
|
|
await this.noSyncButton.click();
|
|
}
|
|
|
|
async typeInviteLink1(email: string) {
|
|
await this.inviteLinkField1.fill(email);
|
|
}
|
|
|
|
async typeInviteLink2(email: string) {
|
|
await this.inviteLinkField2.fill(email);
|
|
}
|
|
|
|
async typeInviteLink3(email: string) {
|
|
await this.inviteLinkField3.fill(email);
|
|
}
|
|
|
|
async clickCopyInviteLink() {
|
|
await this.copyInviteLink.click();
|
|
}
|
|
|
|
async clickFinishButton() {
|
|
await this.finishButton.click();
|
|
}
|
|
}
|