diff --git a/tests/sanity/.env b/tests/sanity/.env index d51aba7616..e5b4e957a9 100644 --- a/tests/sanity/.env +++ b/tests/sanity/.env @@ -4,4 +4,4 @@ PLATFORM_USER='user1' PLATFORM_USER_SECOND='user2' PLATFORM_TOKEN='eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6InVzZXIxIiwid29ya3NwYWNlIjoic2FuaXR5LXdzIn0.hfUCqePHO-WNps2by4B-CYGKIpDpLG0WVCUUtU-SVI4' SETTING=storage.json -SETTING_SECOND=storageSecond.json \ No newline at end of file +SETTING_SECOND=storageSecond.json diff --git a/tests/sanity/tests/login.spec.ts b/tests/sanity/tests/login.spec.ts index 7a25249312..82e1ed1374 100644 --- a/tests/sanity/tests/login.spec.ts +++ b/tests/sanity/tests/login.spec.ts @@ -1,19 +1,52 @@ import { test } from '@playwright/test' -import { PlatformUser } from './utils' +import { PlatformUser, checkIfUrlContains } from './utils' import { LoginPage } from './model/login-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('check login', async ({ page }) => { - page.on('pageerror', (exception) => { - console.log('Uncaught exception:') - console.log(exception.message) - }) - const loginPage = new LoginPage(page) - await loginPage.goto() - await loginPage.login(PlatformUser, '1234') + let loginPage: LoginPage + let commonTrackerPage: CommonTrackerPage + let signupPage: SignUpPage + let trackerNavigationMenuPage: TrackerNavigationMenuPage + let selectWorkspacePage: SelectWorkspacePage - 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 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') }) }) diff --git a/tests/sanity/tests/model/login-page.ts b/tests/sanity/tests/model/login-page.ts index fe0457773b..b76fb09591 100644 --- a/tests/sanity/tests/model/login-page.ts +++ b/tests/sanity/tests/model/login-page.ts @@ -12,7 +12,15 @@ export class LoginPage { inputPassword = (): Locator => this.page.locator('input[name=current-password]') buttonLogin = (): Locator => this.page.locator('button', { hasText: 'Log In' }) 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 { await (await this.page.goto(`${PlatformURI}/login/login`))?.finished() } @@ -21,10 +29,38 @@ export class LoginPage { await this.linkSignUp().click() } + async clickOnRecover (): Promise { + await this.recoverLink().click() + } + + async clickOnRecoveryLogin (): Promise { + await this.recoveryLogin().click() + } + + async clickOnRecoverySignUp (): Promise { + await this.recoverySignUp().click() + } + async login (email: string, password: string): Promise { await this.inputEmail().fill(email) await this.inputPassword().fill(password) expect(await this.buttonLogin().isEnabled()).toBe(true) await this.buttonLogin().click() } + + // ASSERTS + + async checkIfErrorMessageIsShown (): Promise { + await expect(this.invalidPasswordMessage()).toContainText('Invalid password') + } + + async checkIfLoginButtonIsDissaabled (): Promise { + await expect(this.buttonLogin()).toBeDisabled() + } + + async checkIfPasswordRecoveryIsVisible (): Promise { + await expect(this.passwordRecovery()).toBeVisible() + await expect(this.recoveryLoginText()).toBeVisible() + await expect(this.recoverySignUpText()).toBeVisible() + } } diff --git a/tests/sanity/tests/model/profile/user-profile-page.ts b/tests/sanity/tests/model/profile/user-profile-page.ts index 7d609e058b..2adf1c2657 100644 --- a/tests/sanity/tests/model/profile/user-profile-page.ts +++ b/tests/sanity/tests/model/profile/user-profile-page.ts @@ -11,6 +11,10 @@ export class UserProfilePage { applyChangesButton = (): Locator => this.page.locator('.editor-container button:nth-child(3)') addSocialLinksButton = (): Locator => this.page.locator('[id="presentation:string:AddSocialLinks"]') 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) { this.page = page @@ -28,8 +32,21 @@ export class UserProfilePage { await this.profileButton().click() } + async clickLeaveWorkspaceButton (): Promise { + await this.leaveWorkspaceButton().click() + } + + async clickLeaveWorkspaceConfirmButton (): Promise { + await this.leaveWorkspaceConfirmButton().click() + } + + async clickLeaveWorkspaceCancelButton (): Promise { + await this.leaveWorkspaceCancelButton().click() + } + async selectProfileByName (name: string): Promise { await this.selectProfile(name).click() + await this.page.waitForTimeout(1000) } async verifyProfilePageUrl (expectedUrl: string): Promise { @@ -54,4 +71,8 @@ export class UserProfilePage { async applyChanges (): Promise { await this.applyChangesButton().click() } + + async checkIfAccountIsDisabled (): Promise { + await expect(this.accountDissabledMessage()).toContainText('Account is disabled') + } } diff --git a/tests/sanity/tests/model/select-workspace-page.ts b/tests/sanity/tests/model/select-workspace-page.ts index a85ec09994..6290b81bf2 100644 --- a/tests/sanity/tests/model/select-workspace-page.ts +++ b/tests/sanity/tests/model/select-workspace-page.ts @@ -13,8 +13,8 @@ export class SelectWorkspacePage extends CommonPage { buttonCreateWorkspace = (): Locator => this.page.locator('button > span', { hasText: 'Create workspace' }) buttonWorkspaceName = (): Locator => this.page.locator('input') buttonCreateNewWorkspace = (): Locator => this.page.locator('div.form-row button') - workspaceButtonByName = (workspace: string): Locator => this.buttonWorkspace().filter({ hasText: workspace }) + createAnotherWorkspace = (): Locator => this.page.getByRole('link', { name: 'Create workspace' }) async selectWorkspace (workspace: string): Promise { await this.workspaceButtonByName(workspace).click() @@ -24,10 +24,17 @@ export class SelectWorkspacePage extends CommonPage { await this.buttonWorkspaceName().fill(workspaceName) } - async createWorkspace (workspaceName: string): Promise { - await this.buttonCreateWorkspace().waitFor({ state: 'visible' }) - await this.enterWorkspaceName(workspaceName) - expect(await this.buttonCreateNewWorkspace().isEnabled()).toBe(true) - await this.buttonCreateNewWorkspace().click() + async createWorkspace (workspaceName: string, worskpaceNew: boolean = true): Promise { + if (worskpaceNew) { + await this.buttonCreateWorkspace().waitFor({ state: 'visible' }) + await this.enterWorkspaceName(workspaceName) + 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() + } } } diff --git a/tests/sanity/tests/model/signup-page.ts b/tests/sanity/tests/model/signup-page.ts index 9fd25a6df4..55f9911dc2 100644 --- a/tests/sanity/tests/model/signup-page.ts +++ b/tests/sanity/tests/model/signup-page.ts @@ -58,4 +58,8 @@ export class SignUpPage extends CommonPage { await this.buttonSignUp().click() } } + + async checkIfSignUpButtonIsDisabled (): Promise { + await expect(this.buttonSignUp()).toBeDisabled() + } } diff --git a/tests/sanity/tests/model/tracker/common-tracker-page.ts b/tests/sanity/tests/model/tracker/common-tracker-page.ts index 20903dcef0..a9d456dd02 100644 --- a/tests/sanity/tests/model/tracker/common-tracker-page.ts +++ b/tests/sanity/tests/model/tracker/common-tracker-page.ts @@ -93,6 +93,15 @@ export class CommonTrackerPage extends CalendarPage { viewButton = (): Locator => this.page.locator('button:has-text("View")') firstOptionButton = (): Locator => this.page.locator('.antiCard >> button >> nth=0') 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 async selectPanelAndViewlet (panel: string, viewletSelector: string): Promise { @@ -282,4 +291,19 @@ export class CommonTrackerPage extends CalendarPage { await this.buttonMoreActions().click() await this.checkDropdownHasNo(this.page, action) } + + async checkIfMainPanelIsVisible (): Promise { + 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 { + 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() + } } diff --git a/tests/sanity/tests/model/tracker/tracker-navigation-menu-page.ts b/tests/sanity/tests/model/tracker/tracker-navigation-menu-page.ts index c5661f7004..4328ad99f5 100644 --- a/tests/sanity/tests/model/tracker/tracker-navigation-menu-page.ts +++ b/tests/sanity/tests/model/tracker/tracker-navigation-menu-page.ts @@ -30,6 +30,15 @@ export class TrackerNavigationMenuPage extends CommonPage { 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') async pressCreateProjectButton (): Promise { @@ -74,4 +83,18 @@ export class TrackerNavigationMenuPage extends CommonPage { async openComponentsForProject (projectName: string): Promise { await this.componentsLinkForProject(projectName).click() } + + async checkIfTrackerSidebarIsVisible (): Promise { + await expect(this.newIssue()).toBeVisible() + await expect(this.myIssues()).toBeVisible() + await expect(this.allIssues()).toBeVisible() + await expect(this.allProjects()).toBeVisible() + } + + async checkIfTrackerSidebarIsVisibleForLiveProject (): Promise { + await expect(this.issues()).toBeVisible() + await expect(this.components()).toBeVisible() + await expect(this.milestone()).toBeVisible() + await expect(this.templates()).toBeVisible() + } } diff --git a/tests/sanity/tests/utils.ts b/tests/sanity/tests/utils.ts index 0184966f23..f7dc65c1b5 100644 --- a/tests/sanity/tests/utils.ts +++ b/tests/sanity/tests/utils.ts @@ -83,3 +83,11 @@ export async function attachScreenshot (name: string, page: Page): Promise }) await page.screenshot({ path: `screenshots/${name}` }) } + +export async function checkIfUrlContains (page: Page, url: string): Promise { + expect(page.url()).toContain(url) +} + +export async function waitForNetworIdle (page: Page, timeout = 2000): Promise { + await Promise.race([page.waitForLoadState('networkidle'), new Promise((resolve) => setTimeout(resolve, timeout))]) +} diff --git a/tests/sanity/tests/workspace/create.spec.ts b/tests/sanity/tests/workspace/create.spec.ts index 0e4d10769a..5034b864bb 100644 --- a/tests/sanity/tests/workspace/create.spec.ts +++ b/tests/sanity/tests/workspace/create.spec.ts @@ -10,6 +10,8 @@ import { IssuesPage } from '../model/tracker/issues-page' import { IssuesDetailsPage } from '../model/tracker/issues-details-page' import { TrackerNavigationMenuPage } from '../model/tracker/tracker-navigation-menu-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', () => { let loginPage: LoginPage @@ -18,6 +20,7 @@ test.describe('Workspace tests', () => { let leftSideMenuPage: LeftSideMenuPage let trackerNavigationMenuPage: TrackerNavigationMenuPage let issuesPage: IssuesPage + let userProfilePage: UserProfilePage test.beforeEach(async ({ page }) => { loginPage = new LoginPage(page) @@ -26,6 +29,7 @@ test.describe('Workspace tests', () => { leftSideMenuPage = new LeftSideMenuPage(page) trackerNavigationMenuPage = new TrackerNavigationMenuPage(page) issuesPage = new IssuesPage(page) + userProfilePage = new UserProfilePage(page) }) test('Create a workspace with a custom name', async () => { @@ -223,4 +227,26 @@ test.describe('Workspace tests', () => { 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() + }) })