Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sub tab next cases #10

Open
wants to merge 8 commits into
base: 5.5
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
83 changes: 76 additions & 7 deletions src/test/functional/pages/BasePage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,14 @@ export class BasePage {
return this.page.getByText(label, { exact: true }).locator('xpath=../..').getByRole('textbox');
}

protected getToggleByTextLabel(label: string): Locator {
public getToggleByTextLabel(label: string): Locator {
return this.page.getByText(label, { exact: true }).locator('xpath=../..').locator('span');
}

public chooseDropdownOptionByText(option: string) {
return this.page.getByRole('banner').getByText(option)
}

protected getDatePickerByTextLabel(label: string): Locator {
return this.page
.locator('form div')
Expand All @@ -59,17 +63,50 @@ export class BasePage {
.locator('xpath=../..')
.getByText('-- Select --');
}

protected chooseDropdownOptionByText(option: string): Locator {
return this.page.getByRole('option', { name: option });
}

protected getSaveButtonByHeadingSection(heading: string): Locator {
public getSaveButtonByHeadingSection(heading: string): Locator {
return this.page
.getByRole('heading', { name: heading })
.locator('xpath=..')
.getByRole('button', { name: 'Save' });
.getByRole('button', { name: Labels.SAVE })
}

protected getSpanByText(text: string): Locator {
return this.page
.locator('span')
.filter({hasText: text})
}

protected getMenuItemByText(text: string): Locator {
return this.page
.getByRole('menuitem')
.filter({ hasText: text })
}

protected getUsernameInput(): Locator {
return this.page.getByPlaceholder(Labels.USERNAME);
}

protected getPasswordInput(): Locator {
return this.page.getByPlaceholder(Labels.PASSWORD);
}

protected getLoginButton(): Locator {
return this.page.getByRole('button', { name: Labels.LOGIN });
}

async loginUser(mail: string, password: string): Promise<void> {
await this.getUsernameInput().type(mail);
await this.getPasswordInput().type( password);
await this.getLoginButton().click();
}

public async logOut(){
await this.getSpanByText('Admin User').click()
await this.getMenuItemByText(Labels.LOGOUT).click()
}


}

export enum SubPage {
Expand All @@ -85,4 +122,36 @@ export class BasePage {
MAINTENANCE = 'Maintenance',
CLAIM = 'Claim',
BUZZ = 'BUZZ',
ADD_EMPLOYEE = 'Add Employee'
}

export enum Labels {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's generally recommended to name enums in a singular way. So it would be Label instead of Labels. This reflects that each constant within the enum (like USERNAME, PASSWORD, LOGIN, etc.) represents a single, distinct label. This singular naming convention makes the code more intuitive and easier to understand, especially for other developers who might work with it in the future.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right when we use it lebel.specific_label then it is one lebel not more

USERNAME = 'Username',
PASSWORD = 'Password',
CONFIRM_PASSWORD = 'Confirm Password',
LOGIN_DETAILS = 'Create Login Details',
SHARE_PHOTOS = 'Share Photos',
SHARE_VIDEOS = 'Share Videos',
ADD = 'Add',
FIRST_NAME = 'First Name',
LAST_NAME = 'Last Name',
MIDDLE_NAME = 'Middle Name',
SAVE = 'Save',
YES_DELETE = 'Yes, Delete',
DELETE_SELECTED = 'Delete Selected',
TYPE_FOR_HINTS = 'Type for hints...',
SEARCH = "Search",
RESET = "Reset",
LOGIN = 'Login',
LOGOUT = 'Logout',
SHARE = 'Share',
DELETE_POST = 'Delete Post',
EDIT_POST = 'Edit Post',
POST = 'Post',
WHAT_ON_YOUR_MIND = 'What\'s on your mind?',
MOST_LIKED_POST =' Most Liked Posts ',
MOST_COMMENTED_POST = ' Most Commented Posts ',
WRITE_YOUR_COMMENT = 'Write your comment...',
SHARE_VIDEO = 'Share Video',
PASTE_VIDEO_URL = 'Paste Video URL'
}
243 changes: 185 additions & 58 deletions src/test/functional/pages/BuzzPage.ts
Original file line number Diff line number Diff line change
@@ -1,66 +1,194 @@
import { BasePage } from './BasePage';

import { BasePage, Labels } from './BasePage';
import { Locator } from "@playwright/test";
export class BuzzPage extends BasePage {
protected readonly sharePhotosButton = this.page.getByRole('button', { name: 'Share Photos' })
protected readonly fileInputButton = this.page.locator('input[type="file"]');
public readonly sharingSubmitButton = this.page.getByRole('button', { name: 'Share', exact: true })
public readonly threeDotsIcon = this.page.getByRole('button', { name: '' });
protected readonly deletePostParagraphButton = this.page.getByText('Delete Post');
protected readonly editPostParagraphButton = this.page.getByText('Edit Post');
protected readonly confirmDeleteButton = this.page.getByRole('button', { name: 'Yes, Delete' })
protected readonly inpostEditTextField = this.page.getByRole('dialog').locator('textarea')
protected readonly confirmEditedPostButton = this.page.getByRole('dialog').getByRole('button', { name: 'Post' })
protected readonly shareVideoButton = this.page.getByRole('button', { name: 'Share Video' })
protected readonly pasteUrlTextarea = this.page.getByPlaceholder('Paste Video URL')
protected readonly shareVideoParagraph = this.page.getByRole('dialog').getByPlaceholder('What\'s on your mind?')
public readonly heartButton = this.page.locator('#heart-svg')
public readonly mostLikedTab = this.page.getByRole('button', { name: ' Most Liked Posts ' })
public readonly mostCommentedTab = this.page.getByRole('button', { name: ' Most Commented Posts ' })
public readonly textPostBody = this.page.locator('.orangehrm-buzz-post-body-text')
public readonly commentPostCloudButtom = this.page.getByRole('button', { name: '' })
public readonly commentInput = this.page.getByPlaceholder('Write your comment...')
public readonly photoBody = this.page.locator('.orangehrm-buzz-photos')
public readonly videoBody = this.page.locator('.orangehrm-buzz-video')
protected readonly simplePostMessageInput = this.page.getByPlaceholder('What\'s on your mind?')
protected readonly submitSimplePostButton = this.page.getByRole('button', { name: 'Post', exact: true })
public readonly postBody = this.page.locator('.orangehrm-buzz-post-body')
public readonly resharePostButton = this.page.locator('.bi-share-fill')
public readonly resharedTitleText = this.page.locator('.orangehrm-buzz-post-body-original-text')


public async locateElementWithDynamicTextAndPhoto(randomTitle: string) {
const element = this.postBody.locator(`:has(:text('${randomTitle}')):has(.orangehrm-buzz-photos) .oxd-text.oxd-text--p.orangehrm-buzz-post-body-text`)
return element;

public getMostLikedTab(
): Locator {
return this.page.getByRole('button', { name: Labels.MOST_LIKED_POST })
}

public getMostCommentedTab(
): Locator {
return this.page.getByRole('button', { name: Labels.MOST_COMMENTED_POST})
}

public getTextPostBody(
): Locator {
return this.page.locator('.orangehrm-buzz-post-body-text')
}

public getVideoBody(
): Locator {
return this.page.locator('.orangehrm-buzz-video')
}

protected getSubmitSimplePostButton(
): Locator {
return this.page.getByRole('button', { name: Labels.POST, exact: true })
}

protected getPostMessageInput(
): Locator {
return this.page.getByPlaceholder(Labels.WHAT_ON_YOUR_MIND)
}

protected getShareVideoTitle(
): Locator {
return this.page.getByRole('dialog').getByPlaceholder(Labels.WHAT_ON_YOUR_MIND)
}

protected getVideoUrlTextarea(
): Locator {
return this.page.getByPlaceholder(Labels.PASTE_VIDEO_URL)
}

protected getShareVideoButton(
): Locator {
return this.page.getByRole('button', { name: Labels.SHARE_VIDEO })
}

protected getConfirmEditedPostButton(
): Locator {
return this.page.getByRole('dialog').getByRole('button', { name: Labels.POST })
}

protected getPostEditTextarea(
): Locator {
return this.page.getByRole('dialog').locator('textarea')
}

protected getConfirmDeleteButton(
): Locator {
return this.page.getByRole('button', { name: Labels.YES_DELETE});
}

protected getEditButton(
): Locator {
return this.page.getByText(Labels.EDIT_POST);
}

protected getDletePostButton(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo - Delete

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

): Locator {
return this.page.getByText(Labels.DELETE_POST);
}

public getThreeDotsButton(
): Locator {
return this.page.getByRole('button', { name: '' });
}

public getSharingSubmitButton(
): Locator {
return this.page.getByRole('button', { name: Labels.SHARE, exact: true })
}

protected getFileInputButton(
): Locator {
return this.page.locator('input[type="file"]')
}

protected getSharePhotoButton(
): Locator {
return this.page.getByRole('button', { name: Labels.SHARE_PHOTOS })
}

public getCommentInput(
randomTitle: string

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would probably not name this randomTitle but just title. The place where you call this function does not use randomTitle. Even if it would be random from the callers perspective - still using "title" as name makes more sense. Because if you would just pass not a random title, then the parameters name would be more generic.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

): Locator {
return this.page
.locator('.oxd-sheet')
.filter({hasText:randomTitle})
.getByPlaceholder(Labels.WRITE_YOUR_COMMENT)
}

public async locateElementWithDynamicText(randomTitle: string) {
const element = this.postBody.locator(`:has(:text('${randomTitle}'))`)
return element;
public getResharedPostButtonByRandomTitle(
randomTitle: string
): Locator {
return this.page
.locator('.oxd-sheet')
.filter({hasText:randomTitle})
.locator('.bi-share-fill')
}

public getHeartButtonByRandomTitle(
randomTitle: string
): Locator {
return this.page
.locator('.oxd-sheet')
.filter({hasText:randomTitle})
.locator('svg')
}

public getCommentPostButtonByRandomTitle(
randomTitle: string
): Locator {
return this.page
.locator('.oxd-sheet')
.filter({hasText:randomTitle})
.locator('.bi-chat-text-fill')
}

public getPostWithRandomTitleAndPhoto(
randomTitle: string
): Locator {
return this.page
.locator('.orangehrm-buzz-post-body')
.filter({hasText:randomTitle})
.filter({has: this.page.locator('.orangehrm-buzz-photos')})
.locator('.orangehrm-buzz-post-body-text')
}

// public getPostWithRandomTitleAndPhoto(randomTitle: string): Locator {
// return this.page.locator(`.orangehrm-buzz-post-body:has(:text('${randomTitle}')):has(.orangehrm-buzz-photos) .orangehrm-buzz-post-body-text`);
// }
// this also works, let's keep it in codebase for poor times

public getOriginalTextOfReSharedPostWithPhoto(
randomTitle: string
): Locator {
return this.page
.locator('.orangehrm-buzz-post-body')
.filter({hasText:randomTitle})
.filter({has: this.page.locator('.orangehrm-buzz-photos')})
.locator('.orangehrm-buzz-post-body-original-text')
}

public getPostWithRandomTitleWithoutPhoto(
randomTitle: string
): Locator {
return this.page
.locator('.orangehrm-buzz-post-body')
.filter({hasText:randomTitle})
.locator('.orangehrm-buzz-post-body-text')
}

// public getPostWithRandomTitleWithoutPhoto(randomTitle: string): Locator {
// return this.page.locator(`.orangehrm-buzz-post-body:has(:text("${randomTitle}")) .orangehrm-buzz-post-body-text`);
// }
// this also works, let's keep it in codebase for poor times

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does poor times mean? 😄

Copy link
Author

@jstawow jstawow Nov 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poor times means times when we do not know how to do something then we will have 2 soluation maybe in different code only 1 of them will work so i would keep it in code


async sharePost(filePath:string, title:string): Promise<void> {
await this.sharePhotosButton.click();
await this.shareVideoParagraph.type(title)
const fileInput = this.fileInputButton;
async sharePostWithPhoto(filePath:string, title:string): Promise<void> {
await this.getSharePhotoButton().click();
await this.getShareVideoTitle().type(title)
const fileInput = this.getFileInputButton();
if (!fileInput) {
console.error('File input element not found.');
return;
}
await fileInput.setInputFiles(filePath);
await this.sharingSubmitButton.click({force:true});
await this.getSharingSubmitButton().click({force:true});
}

async shareVideo(title:string, videoUrl:string): Promise<void> {
const generateIt = (request: any) => {
return request.url().startsWith('https://jnn-pa.googleapis.com') && request.url().endsWith('/GenerateIT');
};
await this.page.waitForLoadState('networkidle', { timeout: 7000 })
await this.shareVideoButton.click();
await this.shareVideoParagraph.type(title)
await this.pasteUrlTextarea.type(videoUrl)
await this.getShareVideoButton().click();
await this.getShareVideoTitle().type(title)
await this.getVideoUrlTextarea().type(videoUrl)
await this.page.waitForRequest(generateIt)
await this.sharingSubmitButton.click()
await this.getSharingSubmitButton().click()
await this.page.waitForRequest(generateIt)
}

Expand All @@ -74,27 +202,26 @@ export class BuzzPage extends BasePage {
else {
await this.page.waitForTimeout(1500)
}
await this.threeDotsIcon.first().click({force:true})
await this.deletePostParagraphButton.click();
await this.confirmDeleteButton.click();
await this.getThreeDotsButton().first().dblclick({force:true})
await this.getDletePostButton().click();
await this.getConfirmDeleteButton().click();
}

async editTheNewestPost(finalPostText: string): Promise<void> {
await this.threeDotsIcon.first().click()
await this.editPostParagraphButton.click();
await this.inpostEditTextField.clear()
await this.inpostEditTextField.fill(finalPostText)
await this.confirmEditedPostButton.click()
await this.getThreeDotsButton().first().click()
await this.getEditButton().click();
await this.getPostEditTextarea().fill(finalPostText)
await this.getConfirmEditedPostButton().click()
}

async sendSimplePost(simplePostMessage:string): Promise<void> {
await this.simplePostMessageInput.type(simplePostMessage)
await this.submitSimplePostButton.click()
await this.getPostMessageInput().type(simplePostMessage)
await this.getSubmitSimplePostButton().click()
}

async resharePostOfOther(title:string): Promise<void> {
await this.resharePostButton.last().click()
await this.shareVideoParagraph.type(title)
await this.sharingSubmitButton.click()
async reshareOtherPost(oldTitle:string, newTitle:string): Promise<void> {
await this.getResharedPostButtonByRandomTitle(oldTitle).click()
await this.getShareVideoTitle().type(newTitle)
await this.getSharingSubmitButton().click()
}
}
Loading