Add livness check for login and workspace (#5532)

Signed-off-by: Jasmin <jasmin@hardcoreeng.com>
This commit is contained in:
JasminMus 2024-05-08 19:35:24 +02:00 committed by GitHub
parent 2c3ffba681
commit d1e0790d08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 199 additions and 17 deletions

View File

@ -1,19 +1,52 @@
import { test } from '@playwright/test' import { test } from '@playwright/test'
import { PlatformUser } from './utils' import { PlatformUser, checkIfUrlContains } from './utils'
import { LoginPage } from './model/login-page' import { LoginPage } from './model/login-page'
import { SelectWorkspacePage } from './model/select-workspace-page' import { SelectWorkspacePage } from './model/select-workspace-page'
import { CommonTrackerPage } from './model/tracker/common-tracker-page'
import { TrackerNavigationMenuPage } from './model/tracker/tracker-navigation-menu-page'
import { SignUpPage } from './model/signup-page'
test.describe('login test', () => { test.describe('login test', () => {
test('check login', async ({ page }) => { let loginPage: LoginPage
page.on('pageerror', (exception) => { let commonTrackerPage: CommonTrackerPage
console.log('Uncaught exception:') let signupPage: SignUpPage
console.log(exception.message) let trackerNavigationMenuPage: TrackerNavigationMenuPage
}) let selectWorkspacePage: SelectWorkspacePage
const loginPage = new LoginPage(page)
await loginPage.goto()
await loginPage.login(PlatformUser, '1234')
const selectWorkspacePage = new SelectWorkspacePage(page) test.beforeEach(async ({ page }) => {
loginPage = new LoginPage(page)
commonTrackerPage = new CommonTrackerPage(page)
signupPage = new SignUpPage(page)
trackerNavigationMenuPage = new TrackerNavigationMenuPage(page)
selectWorkspacePage = new SelectWorkspacePage(page)
await loginPage.goto()
})
test('check login', async () => {
await loginPage.login(PlatformUser, '1234')
await selectWorkspacePage.selectWorkspace('SanityTest') await selectWorkspacePage.selectWorkspace('SanityTest')
await commonTrackerPage.checkIfMainPanelIsVisible()
await trackerNavigationMenuPage.checkIfTrackerSidebarIsVisible()
})
test('check login with wrong user and if the button is disabled ', async ({ page }) => {
await loginPage.checkIfLoginButtonIsDissaabled()
await loginPage.login(PlatformUser, 'wrong-password')
await loginPage.checkIfErrorMessageIsShown()
})
test('check if user is able to go to to recovery, then login and then signup', async ({ page }) => {
await checkIfUrlContains(page, '/login')
await loginPage.checkIfLoginButtonIsDissaabled()
await loginPage.clickOnRecover()
await checkIfUrlContains(page, '/password')
await loginPage.checkIfPasswordRecoveryIsVisible()
await loginPage.clickOnRecoveryLogin()
await checkIfUrlContains(page, '/login')
await loginPage.checkIfLoginButtonIsDissaabled()
await loginPage.clickOnRecover()
await loginPage.clickOnRecoverySignUp()
await signupPage.checkIfSignUpButtonIsDisabled()
await checkIfUrlContains(page, '/signup')
}) })
}) })

View File

@ -12,7 +12,15 @@ export class LoginPage {
inputPassword = (): Locator => this.page.locator('input[name=current-password]') inputPassword = (): Locator => this.page.locator('input[name=current-password]')
buttonLogin = (): Locator => this.page.locator('button', { hasText: 'Log In' }) buttonLogin = (): Locator => this.page.locator('button', { hasText: 'Log In' })
linkSignUp = (): Locator => this.page.locator('a.title', { hasText: 'Sign Up' }) linkSignUp = (): Locator => this.page.locator('a.title', { hasText: 'Sign Up' })
invalidPasswordMessage = (): Locator => this.page.getByText('Invalid password')
recoverLink = (): Locator => this.page.getByRole('link', { name: 'Recover' })
passwordRecovery = (): Locator => this.page.getByText('Password recovery')
recoveryLoginText = (): Locator => this.page.getByText('Know your password? Log In')
recoverySignUpText = (): Locator => this.page.getByText('Do not have an account? Sign Up')
recoveryLogin = (): Locator => this.page.getByRole('link', { name: 'Log In' })
recoverySignUp = (): Locator => this.page.getByRole('link', { name: 'Sign Up' })
// ACTIONS
async goto (): Promise<void> { async goto (): Promise<void> {
await (await this.page.goto(`${PlatformURI}/login/login`))?.finished() await (await this.page.goto(`${PlatformURI}/login/login`))?.finished()
} }
@ -21,10 +29,38 @@ export class LoginPage {
await this.linkSignUp().click() await this.linkSignUp().click()
} }
async clickOnRecover (): Promise<void> {
await this.recoverLink().click()
}
async clickOnRecoveryLogin (): Promise<void> {
await this.recoveryLogin().click()
}
async clickOnRecoverySignUp (): Promise<void> {
await this.recoverySignUp().click()
}
async login (email: string, password: string): Promise<void> { async login (email: string, password: string): Promise<void> {
await this.inputEmail().fill(email) await this.inputEmail().fill(email)
await this.inputPassword().fill(password) await this.inputPassword().fill(password)
expect(await this.buttonLogin().isEnabled()).toBe(true) expect(await this.buttonLogin().isEnabled()).toBe(true)
await this.buttonLogin().click() await this.buttonLogin().click()
} }
// ASSERTS
async checkIfErrorMessageIsShown (): Promise<void> {
await expect(this.invalidPasswordMessage()).toContainText('Invalid password')
}
async checkIfLoginButtonIsDissaabled (): Promise<void> {
await expect(this.buttonLogin()).toBeDisabled()
}
async checkIfPasswordRecoveryIsVisible (): Promise<void> {
await expect(this.passwordRecovery()).toBeVisible()
await expect(this.recoveryLoginText()).toBeVisible()
await expect(this.recoverySignUpText()).toBeVisible()
}
} }

View File

@ -11,6 +11,10 @@ export class UserProfilePage {
applyChangesButton = (): Locator => this.page.locator('.editor-container button:nth-child(3)') applyChangesButton = (): Locator => this.page.locator('.editor-container button:nth-child(3)')
addSocialLinksButton = (): Locator => this.page.locator('[id="presentation:string:AddSocialLinks"]') addSocialLinksButton = (): Locator => this.page.locator('[id="presentation:string:AddSocialLinks"]')
selectProfile = (name: string): Locator => this.page.locator(`text=${name}`) selectProfile = (name: string): Locator => this.page.locator(`text=${name}`)
leaveWorkspaceButton = (): Locator => this.page.getByRole('button', { name: 'Leave workspace' })
leaveWorkspaceCancelButton = (): Locator => this.page.getByRole('button', { name: 'Cancel' })
leaveWorkspaceConfirmButton = (): Locator => this.page.getByRole('button', { name: 'Ok' })
accountDissabledMessage = (): Locator => this.page.getByRole('heading')
constructor (page: Page) { constructor (page: Page) {
this.page = page this.page = page
@ -28,8 +32,21 @@ export class UserProfilePage {
await this.profileButton().click() await this.profileButton().click()
} }
async clickLeaveWorkspaceButton (): Promise<void> {
await this.leaveWorkspaceButton().click()
}
async clickLeaveWorkspaceConfirmButton (): Promise<void> {
await this.leaveWorkspaceConfirmButton().click()
}
async clickLeaveWorkspaceCancelButton (): Promise<void> {
await this.leaveWorkspaceCancelButton().click()
}
async selectProfileByName (name: string): Promise<void> { async selectProfileByName (name: string): Promise<void> {
await this.selectProfile(name).click() await this.selectProfile(name).click()
await this.page.waitForTimeout(1000)
} }
async verifyProfilePageUrl (expectedUrl: string): Promise<void> { async verifyProfilePageUrl (expectedUrl: string): Promise<void> {
@ -54,4 +71,8 @@ export class UserProfilePage {
async applyChanges (): Promise<void> { async applyChanges (): Promise<void> {
await this.applyChangesButton().click() await this.applyChangesButton().click()
} }
async checkIfAccountIsDisabled (): Promise<void> {
await expect(this.accountDissabledMessage()).toContainText('Account is disabled')
}
} }

View File

@ -13,8 +13,8 @@ export class SelectWorkspacePage extends CommonPage {
buttonCreateWorkspace = (): Locator => this.page.locator('button > span', { hasText: 'Create workspace' }) buttonCreateWorkspace = (): Locator => this.page.locator('button > span', { hasText: 'Create workspace' })
buttonWorkspaceName = (): Locator => this.page.locator('input') buttonWorkspaceName = (): Locator => this.page.locator('input')
buttonCreateNewWorkspace = (): Locator => this.page.locator('div.form-row button') buttonCreateNewWorkspace = (): Locator => this.page.locator('div.form-row button')
workspaceButtonByName = (workspace: string): Locator => this.buttonWorkspace().filter({ hasText: workspace }) workspaceButtonByName = (workspace: string): Locator => this.buttonWorkspace().filter({ hasText: workspace })
createAnotherWorkspace = (): Locator => this.page.getByRole('link', { name: 'Create workspace' })
async selectWorkspace (workspace: string): Promise<void> { async selectWorkspace (workspace: string): Promise<void> {
await this.workspaceButtonByName(workspace).click() await this.workspaceButtonByName(workspace).click()
@ -24,10 +24,17 @@ export class SelectWorkspacePage extends CommonPage {
await this.buttonWorkspaceName().fill(workspaceName) await this.buttonWorkspaceName().fill(workspaceName)
} }
async createWorkspace (workspaceName: string): Promise<void> { async createWorkspace (workspaceName: string, worskpaceNew: boolean = true): Promise<void> {
await this.buttonCreateWorkspace().waitFor({ state: 'visible' }) if (worskpaceNew) {
await this.enterWorkspaceName(workspaceName) await this.buttonCreateWorkspace().waitFor({ state: 'visible' })
expect(await this.buttonCreateNewWorkspace().isEnabled()).toBe(true) await this.enterWorkspaceName(workspaceName)
await this.buttonCreateNewWorkspace().click() expect(await this.buttonCreateNewWorkspace().isEnabled()).toBe(true)
await this.buttonCreateNewWorkspace().click()
} else {
await this.createAnotherWorkspace().click()
await this.enterWorkspaceName(workspaceName)
expect(await this.buttonCreateNewWorkspace().isEnabled()).toBe(true)
await this.buttonCreateNewWorkspace().click()
}
} }
} }

View File

@ -58,4 +58,8 @@ export class SignUpPage extends CommonPage {
await this.buttonSignUp().click() await this.buttonSignUp().click()
} }
} }
async checkIfSignUpButtonIsDisabled (): Promise<void> {
await expect(this.buttonSignUp()).toBeDisabled()
}
} }

View File

@ -93,6 +93,15 @@ export class CommonTrackerPage extends CalendarPage {
viewButton = (): Locator => this.page.locator('button:has-text("View")') viewButton = (): Locator => this.page.locator('button:has-text("View")')
firstOptionButton = (): Locator => this.page.locator('.antiCard >> button >> nth=0') firstOptionButton = (): Locator => this.page.locator('.antiCard >> button >> nth=0')
assigneeMenuItem = (): Locator => this.page.locator('.menu-item:has-text("Assignee")') assigneeMenuItem = (): Locator => this.page.locator('.menu-item:has-text("Assignee")')
header = (): Locator => this.page.getByText('Issues All Active Backlog')
filter = (): Locator => this.page.getByRole('button', { name: 'Filter' })
view = (): Locator => this.page.getByRole('button', { name: 'View' })
showMore = (): Locator => this.page.getByRole('button', { name: 'Show' })
task1 = (): Locator => this.page.getByRole('link', { name: 'Welcome to Huly! 🌟' })
task2 = (): Locator => this.page.getByRole('link', { name: 'Create your first Project 📌' })
task3 = (): Locator => this.page.getByRole('link', { name: 'Create your first Issue 📝' })
task4 = (): Locator => this.page.getByRole('link', { name: 'Schedule your first Todo 📆' })
task5 = (): Locator => this.page.getByRole('link', { name: 'Explore all Huly has to offer' })
// Actions // Actions
async selectPanelAndViewlet (panel: string, viewletSelector: string): Promise<void> { async selectPanelAndViewlet (panel: string, viewletSelector: string): Promise<void> {
@ -282,4 +291,19 @@ export class CommonTrackerPage extends CalendarPage {
await this.buttonMoreActions().click() await this.buttonMoreActions().click()
await this.checkDropdownHasNo(this.page, action) await this.checkDropdownHasNo(this.page, action)
} }
async checkIfMainPanelIsVisible (): Promise<void> {
await expect(this.header()).toBeVisible({ timeout: 60000 })
await expect(this.filter()).toBeVisible()
await expect(this.view()).toBeVisible()
await expect(this.showMore()).toBeVisible()
}
async checkIfTasksAreVisable (): Promise<void> {
await expect(this.task1()).toBeVisible()
await expect(this.task2()).toBeVisible()
await expect(this.task3()).toBeVisible()
await expect(this.task4()).toBeVisible()
await expect(this.task5()).toBeVisible()
}
} }

View File

@ -30,6 +30,15 @@ export class TrackerNavigationMenuPage extends CommonPage {
hasText: 'Components' hasText: 'Components'
}) })
newIssue = (): Locator => this.page.locator('button', { hasText: 'New issue' })
myIssues = (): Locator => this.page.getByRole('link', { name: 'My issues', exact: true })
allIssues = (): Locator => this.page.getByRole('link', { name: 'All issues', exact: true })
allProjects = (): Locator => this.page.getByRole('link', { name: 'All projects' })
issues = (): Locator => this.page.getByRole('link', { name: 'Issues', exact: true })
components = (): Locator => this.page.getByRole('link', { name: 'Components' })
milestone = (): Locator => this.page.getByRole('link', { name: 'Milestones' })
templates = (): Locator => this.page.getByRole('link', { name: 'Templates' })
createProjectButton = (): Locator => this.buttonCreateProject().locator('button.small') createProjectButton = (): Locator => this.buttonCreateProject().locator('button.small')
async pressCreateProjectButton (): Promise<void> { async pressCreateProjectButton (): Promise<void> {
@ -74,4 +83,18 @@ export class TrackerNavigationMenuPage extends CommonPage {
async openComponentsForProject (projectName: string): Promise<void> { async openComponentsForProject (projectName: string): Promise<void> {
await this.componentsLinkForProject(projectName).click() await this.componentsLinkForProject(projectName).click()
} }
async checkIfTrackerSidebarIsVisible (): Promise<void> {
await expect(this.newIssue()).toBeVisible()
await expect(this.myIssues()).toBeVisible()
await expect(this.allIssues()).toBeVisible()
await expect(this.allProjects()).toBeVisible()
}
async checkIfTrackerSidebarIsVisibleForLiveProject (): Promise<void> {
await expect(this.issues()).toBeVisible()
await expect(this.components()).toBeVisible()
await expect(this.milestone()).toBeVisible()
await expect(this.templates()).toBeVisible()
}
} }

View File

@ -83,3 +83,11 @@ export async function attachScreenshot (name: string, page: Page): Promise<void>
}) })
await page.screenshot({ path: `screenshots/${name}` }) await page.screenshot({ path: `screenshots/${name}` })
} }
export async function checkIfUrlContains (page: Page, url: string): Promise<void> {
expect(page.url()).toContain(url)
}
export async function waitForNetworIdle (page: Page, timeout = 2000): Promise<void> {
await Promise.race([page.waitForLoadState('networkidle'), new Promise((resolve) => setTimeout(resolve, timeout))])
}

View File

@ -10,6 +10,8 @@ import { IssuesPage } from '../model/tracker/issues-page'
import { IssuesDetailsPage } from '../model/tracker/issues-details-page' import { IssuesDetailsPage } from '../model/tracker/issues-details-page'
import { TrackerNavigationMenuPage } from '../model/tracker/tracker-navigation-menu-page' import { TrackerNavigationMenuPage } from '../model/tracker/tracker-navigation-menu-page'
import { SignInJoinPage } from '../model/signin-page' import { SignInJoinPage } from '../model/signin-page'
import { UserProfilePage } from '../model/profile/user-profile-page'
import { faker } from '@faker-js/faker'
test.describe('Workspace tests', () => { test.describe('Workspace tests', () => {
let loginPage: LoginPage let loginPage: LoginPage
@ -18,6 +20,7 @@ test.describe('Workspace tests', () => {
let leftSideMenuPage: LeftSideMenuPage let leftSideMenuPage: LeftSideMenuPage
let trackerNavigationMenuPage: TrackerNavigationMenuPage let trackerNavigationMenuPage: TrackerNavigationMenuPage
let issuesPage: IssuesPage let issuesPage: IssuesPage
let userProfilePage: UserProfilePage
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
loginPage = new LoginPage(page) loginPage = new LoginPage(page)
@ -26,6 +29,7 @@ test.describe('Workspace tests', () => {
leftSideMenuPage = new LeftSideMenuPage(page) leftSideMenuPage = new LeftSideMenuPage(page)
trackerNavigationMenuPage = new TrackerNavigationMenuPage(page) trackerNavigationMenuPage = new TrackerNavigationMenuPage(page)
issuesPage = new IssuesPage(page) issuesPage = new IssuesPage(page)
userProfilePage = new UserProfilePage(page)
}) })
test('Create a workspace with a custom name', async () => { test('Create a workspace with a custom name', async () => {
@ -223,4 +227,26 @@ test.describe('Workspace tests', () => {
await leftSideMenuPageSecond.clickTracker() await leftSideMenuPageSecond.clickTracker()
}) })
}) })
test('User can leave workspace', async () => {
const newUser: SignUpData = {
firstName: faker.person.firstName(),
lastName: faker.person.lastName(),
email: faker.internet.email(),
password: '1234'
}
const newWorkspaceName = `Some HULY #@$ WS - ${generateId(12)}`
await loginPage.goto()
await loginPage.clickSignUp()
await signUpPage.signUp(newUser)
await selectWorkspacePage.createWorkspace(newWorkspaceName)
await trackerNavigationMenuPage.checkIfTrackerSidebarIsVisible()
await userProfilePage.openProfileMenu()
await userProfilePage.selectProfileByName(newUser.lastName + ' ' + newUser.firstName)
await userProfilePage.clickLeaveWorkspaceButton()
await userProfilePage.clickLeaveWorkspaceCancelButton()
await userProfilePage.clickLeaveWorkspaceButton()
await userProfilePage.clickLeaveWorkspaceConfirmButton()
await userProfilePage.checkIfAccountIsDisabled()
})
}) })