Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ export class AccountPage {
readonly usernameDisplay: Locator;
readonly editEmailButton: Locator;
readonly editDisplayNameButton: Locator;
readonly editUserNameButton: Locator;
readonly emailInput: Locator;
readonly displayNameInput: Locator;
readonly userNameInput: Locator;
readonly resetPasswordButton: Locator;
readonly receiveNewsletterCheckbox: Locator;
readonly typingIndicator: Locator;
Expand All @@ -56,8 +58,10 @@ export class AccountPage {
this.logoutButton = page.getByTestId('do-logout');
this.editEmailButton = page.getByTestId('go-edit-email');
this.editDisplayNameButton = page.getByTestId('go-edit-email');
this.editUserNameButton = page.getByRole('button', {name: 'Username'});
this.emailInput = page.getByTestId('enter-email-input');
this.displayNameInput = page.getByTestId('enter-displayname-input');
this.userNameInput = page.getByLabel('Username');
this.emailDisplay = page.getByTestId('email-display');
this.nameDisplay = page.getByTestId('displayname-display');
this.domainDisplay = page.getByTestId('item-enriched-value');
Expand Down Expand Up @@ -141,6 +145,12 @@ export class AccountPage {
await this.displayNameInput.press('Enter');
}

async changeUserName(newUserName: string) {
await this.editUserNameButton.click();
await this.userNameInput.fill(newUserName);
await this.userNameInput.press('Enter');
}

statusOption(status: 'Away' | 'Busy' | 'Available' | 'None') {
return this.page.getByRole('button', {name: new RegExp(`${status}`, 'i')});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ import {Page, Locator} from '@playwright/test';
export class SetUsernamePage {
readonly handleInput: Locator;
readonly nextButton: Locator;
readonly errorMessage: Locator;

constructor(page: Page) {
this.handleInput = page.locator('[data-uie-name="enter-handle"]');
this.nextButton = page.locator('[data-uie-name="do-send-handle"]');
this.errorMessage = page.getByTestId('error-message');
}

async setUsername(username: string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,162 @@
.toEqual(expect.arrayContaining([expect.stringContaining(expectedLog)]));
});

test('Verify new username is synced across the devices', {tag: ['@TC-1938', '@regression']}, async ({createPage}) => {
const {components, pages} = PageManager.from(await createPage(withLogin(memberA))).webapp;
await components.conversationSidebar().clickPreferencesButton();
// Verify initial username
await expect(pages.account().usernameDisplay).toContainText(memberA.username);

// Change username to a unique name
const newUserName = `user_${Date.now()}`;
await pages.account().changeUserName(newUserName);
await expect(pages.account().usernameDisplay).toContainText(newUserName);

// Setup second device session
const {components: userA2DeviceComponents} = PageManager.from(
await createPage(withLogin(memberA, {confirmNewHistory: true})),
).webapp;

// Verify sync on second device
await expect(userA2DeviceComponents.conversationSidebar().personalUserName).toContainText(newUserName);
});

test(
'Verify autogeneration of a username for a user',
{tag: ['@TC-1939', '@regression']},
async ({createPage, api}) => {
const usernameScenarios = [
{firstName: 'Jack', expectedUsername: 'jack'},
{firstName: 'Jack.Wireson', expectedUsername: 'jackwireson'},
{firstName: 'Æéÿüíøšłźçñ', expectedUsername: 'aeeyueioslzcn'},
{firstName: 'Даша', expectedUsername: 'dasha'},
{firstName: 'داريا', expectedUsername: 'darya'},
{firstName: 'Jack😼', expectedUsername: 'jack'},
];

await Promise.all(
usernameScenarios.map(async ({firstName, expectedUsername}) => {
return test.step(`Scenario: ${firstName} -> ${expectedUsername}`, async () => {
const userA = getUser({firstName});
const userPage = await createPage();
const userPageManager = PageManager.from(userPage);
const {pages, components, modals} = userPageManager.webapp;

await test.step('Register user and handle verification', async () => {
await userPageManager.openMainPage();
await pages.singleSignOn().enterEmailOnSSOPage(userA.email);
await pages.welcome().clickCreateAccountButton();
await pages.welcome().clickCreatePersonalAccountButton();

await pages.registration().fillInUserInfo(userA);
await pages.registration().toggleTermsCheckbox();
await pages.registration().clickSubmitButton();

await expect(pages.emailVerification().verificationCodeInputLabel).toBeVisible();

const verificationCode = await api.brig.getActivationCodeForEmail(userA.email);
await pages.emailVerification().enterVerificationCode(verificationCode);
await modals.marketingConsent().clickConfirmButton();
});

try {
await test.step('Verify autogenerated username on registration and profile', async () => {
await expect(pages.setUsername().handleInput).toHaveValue(new RegExp(expectedUsername));

await pages.setUsername().clickNextButton();
await pages.registerSuccess().clickOpenWireWebButton();
await modals.confirm().cancelButton.click({timeout: LOGIN_TIMEOUT});

await components.conversationSidebar().clickPreferencesButton();
await expect(pages.account().usernameDisplay).toContainText(expectedUsername);
});
} finally {
await test.step('Cleanup: delete account and close page', async () => {
await pages.account().clickDeleteAccountButton();
await expect(modals.confirm().modal).toBeVisible();
await modals.confirm().actionButton.click();

const deletionUrl = await api.inbucket.getAccountDeletionURL(userA.email);

await userPageManager.openNewTab(deletionUrl, async tab => {
await tab.webapp.pages.deleteAccount().deleteAccountButton.click();
await expect(tab.webapp.pages.deleteAccount().accountDeletedHeadline).toContainText(
'Account deleted',
);
});

await userPage.close();
});
}
});
}),
);
},
);

test('Verify username is unique', {tag: ['@TC-1942', '@regression']}, async ({createPage, createUser, api}) => {
const userA = await createUser();

const userB = getUser();
const userPage = await createPage();
const userPageManager = PageManager.from(userPage);
const {pages, components, modals} = userPageManager.webapp;

await test.step('Register User B before username selection', async () => {
await userPageManager.openMainPage();
await pages.singleSignOn().enterEmailOnSSOPage(userB.email);
await pages.welcome().clickCreateAccountButton();
await pages.welcome().clickCreatePersonalAccountButton();

await pages.registration().fillInUserInfo(userB);
await pages.registration().toggleTermsCheckbox();
await pages.registration().clickSubmitButton();
await expect(pages.emailVerification().verificationCodeInputLabel).toBeVisible();

const verificationCode = await api.brig.getActivationCodeForEmail(userB.email);
await pages.emailVerification().enterVerificationCode(verificationCode);
await modals.marketingConsent().clickConfirmButton();
Comment thread
zhannach marked this conversation as resolved.
});

await test.step('Validate username uniqueness error during account creating', async () => {
await pages.setUsername().setUsername(userA.username);
await pages.setUsername().clickNextButton();
await expect(pages.setUsername().errorMessage).toContainText('This username is already taken');

// Proceed successfully with User B's unique username
await pages.setUsername().setUsername(userB.username);
await pages.setUsername().clickNextButton();
await pages.registerSuccess().clickOpenWireWebButton();
await modals.confirm().cancelButton.click({timeout: LOGIN_TIMEOUT});
});

await test.step('Validate username uniqueness error inside Profile Settings', async () => {
await components.conversationSidebar().clickPreferencesButton();
await expect(pages.account().usernameDisplay).toContainText(userB.username);
await pages.account().changeUserName(userA.username);

// TODO(WPB-25926): Currently the error message isn't shown correctly in the UI

Check warning on line 337 in apps/webapp/test/e2e_tests/specs/AccountSettings/accountSettings.spec.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Complete the task associated to this "TODO" comment.

See more on https://sonarcloud.io/project/issues?id=wireapp_wire-webapp&issues=AZ50tAAKCtVEn5qYqE29&open=AZ50tAAKCtVEn5qYqE29&pullRequest=21405
// await expect(userPage.getByText('Already taken')).toBeVisible();
// await pages.account().userNameInput.fill(userB.username);
// await pages.account().userNameInput.press('Enter');

await expect(pages.account().usernameDisplay).toContainText(userB.username);
Comment thread
zhannach marked this conversation as resolved.
});

await test.step('Delete user', async () => {
await components.conversationSidebar().clickPreferencesButton();
await pages.account().clickDeleteAccountButton();
await expect(modals.confirm().modalTitle).toContainText('Delete account');
await modals.confirm().actionButton.click();
const url = await api.inbucket.getAccountDeletionURL(userB.email);

await userPageManager.openNewTab(url, async tab => {
await tab.webapp.pages.deleteAccount().deleteAccountButton.click();
await expect(tab.webapp.pages.deleteAccount().accountDeletedHeadline).toContainText('Account deleted');
});
});
});

test(
'I want to see the Full Name wherever my name gets displayed',
{tag: ['@TC-1948', '@regression']},
Expand Down
Loading