mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-29 03:34:31 +00:00
282 lines
9.2 KiB
TypeScript
282 lines
9.2 KiB
TypeScript
import { faker } from '@faker-js/faker'
|
|
import { APIRequestContext, Browser, BrowserContext, Locator, Page, expect } from '@playwright/test'
|
|
import { attachment } from 'allure-js-commons'
|
|
import path from 'path'
|
|
import { ApiEndpoint } from './API/Api'
|
|
import { TestData } from './chat/types'
|
|
import { SignUpData } from './model/common-types'
|
|
import { LeftSideMenuPage } from './model/left-side-menu-page'
|
|
import { LoginPage } from './model/login-page'
|
|
import { SelectWorkspacePage } from './model/select-workspace-page'
|
|
import { SignInJoinPage } from './model/signin-page'
|
|
|
|
export const PlatformURI = process.env.PLATFORM_URI as string
|
|
export const PlatformTransactor = process.env.PLATFORM_TRANSACTOR as string
|
|
export const PlatformUser = process.env.PLATFORM_USER as string
|
|
export const PlatformUserSecond = process.env.PLATFORM_USER_SECOND as string
|
|
export const PlatformSetting = process.env.SETTING as string
|
|
export const PlatformSettingSecond = process.env.SETTING_SECOND as string
|
|
|
|
export const DefaultWorkspace = 'SanityTest'
|
|
export const LocalUrl = process.env.LOCAL_URL as string
|
|
export const DevUrl = process.env.DEV_URL as string
|
|
export const StagingUrl = process.env.STAGING_URL as string
|
|
|
|
export function generateTestData (): TestData {
|
|
const generateWordStartingWithA = (): string => {
|
|
const randomWord = faker.lorem.word()
|
|
return 'A' + randomWord.slice(1)
|
|
}
|
|
|
|
return {
|
|
workspaceName: faker.lorem.word(),
|
|
userName: faker.internet.userName(),
|
|
firstName: faker.person.firstName(),
|
|
lastName: faker.person.lastName(),
|
|
channelName: generateWordStartingWithA()
|
|
}
|
|
}
|
|
|
|
export function getTimeForPlanner (plusHours: number = 0, cropHours: number = 0): string {
|
|
let hour = new Date().getHours()
|
|
hour = hour < 1 + cropHours ? 1 + cropHours : hour >= 22 - cropHours ? 22 - cropHours : hour
|
|
hour += plusHours
|
|
const ampm = hour < 12 || hour === 24 ? 'am' : 'pm'
|
|
hour -= hour > 12 ? 12 : 0
|
|
|
|
return `${hour}${ampm}`
|
|
}
|
|
|
|
export function getNextHourTimeForPlanner (): string {
|
|
let hour = new Date().getHours() + 1
|
|
const ampm = hour < 13 ? 'am' : 'pm'
|
|
hour = hour < 1 ? 1 : hour >= 11 && hour < 13 ? 11 : hour >= 22 ? 10 : hour > 12 ? hour - 12 : hour
|
|
|
|
return `${hour}${ampm}`
|
|
}
|
|
|
|
// Consistent data
|
|
export const workspaceName = faker.lorem.word()
|
|
export const userName = faker.internet.userName()
|
|
export const firstName = faker.person.firstName()
|
|
export const lastName = faker.person.lastName()
|
|
export const channelName = faker.lorem.word()
|
|
export const email = faker.internet.email()
|
|
|
|
function toHex (value: number, chars: number): string {
|
|
const result = value.toString(16)
|
|
if (result.length < chars) {
|
|
return '0'.repeat(chars - result.length) + result
|
|
}
|
|
return result
|
|
}
|
|
|
|
let counter = 0
|
|
const random = toHex((Math.random() * (1 << 24)) | 0, 6) + toHex((Math.random() * (1 << 16)) | 0, 4)
|
|
|
|
function timestamp (): string {
|
|
const time = (Date.now() / 1000) | 0
|
|
return toHex(time, 8)
|
|
}
|
|
|
|
function count (): string {
|
|
const val = counter++ & 0xffffff
|
|
return toHex(val, 6)
|
|
}
|
|
|
|
export async function setTestOptions (page: Page): Promise<void> {
|
|
await page.evaluate(() => {
|
|
localStorage.setItem('#platform.notification.timeout', '0')
|
|
localStorage.setItem('#platform.testing.enabled', 'true')
|
|
localStorage.setItem('#platform.lazy.loading', 'false')
|
|
})
|
|
}
|
|
|
|
/**
|
|
* @public
|
|
* @returns
|
|
*/
|
|
export function generateId (len = 100): string {
|
|
const v = timestamp() + random
|
|
let s = v.length - len
|
|
if (s < 0) {
|
|
s = 0
|
|
}
|
|
const r = v.slice(s, v.length) + count()
|
|
return r
|
|
}
|
|
|
|
/**
|
|
* Finds a search field on the page, fills it with
|
|
* the provided string, and returns a locator
|
|
*
|
|
* @export
|
|
* @param {Page} page
|
|
* @param {string} search
|
|
* @returns {Promise<Locator>}
|
|
*/
|
|
export async function fillSearch (page: Page, search: string): Promise<Locator> {
|
|
await page.locator('.searchInput-icon').click()
|
|
const searchBox = page.locator('input[placeholder="Search"]')
|
|
|
|
await searchBox.fill(search)
|
|
await searchBox.press('Enter')
|
|
|
|
return searchBox
|
|
}
|
|
|
|
export async function getSecondPage (browser: Browser): Promise<{ page: Page, context: BrowserContext } & Disposable> {
|
|
const userSecondContext = await browser.newContext({ storageState: PlatformSettingSecond })
|
|
const newPage = await userSecondContext.newPage()
|
|
return {
|
|
page: newPage,
|
|
context: userSecondContext,
|
|
[Symbol.dispose]: () => {
|
|
void newPage
|
|
.close()
|
|
.finally(() => {
|
|
void userSecondContext.close().catch(() => {})
|
|
})
|
|
.catch(() => {})
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function getSecondPageByInvite (
|
|
browser: Browser,
|
|
linkText: string | null,
|
|
newUser: SignUpData
|
|
): Promise<{ page: Page, context: BrowserContext } & Disposable> {
|
|
const userSecondContext = await browser.newContext({ storageState: PlatformSettingSecond })
|
|
const newPage = await userSecondContext.newPage()
|
|
await newPage.goto(linkText ?? '')
|
|
const joinPage: SignInJoinPage = new SignInJoinPage(newPage)
|
|
await joinPage.join(newUser)
|
|
|
|
return {
|
|
page: newPage,
|
|
context: userSecondContext,
|
|
[Symbol.dispose]: () => {
|
|
void newPage
|
|
.close()
|
|
.finally(() => {
|
|
void userSecondContext.close().catch(() => {})
|
|
})
|
|
.catch(() => {})
|
|
}
|
|
}
|
|
}
|
|
|
|
export function expectToContainsOrdered (val: Locator, text: string[], timeout?: number): Promise<void> {
|
|
const origIssuesExp = new RegExp('.*' + text.join('.*') + '.*')
|
|
return expect(val).toHaveText(origIssuesExp, { timeout })
|
|
}
|
|
|
|
export async function * iterateLocator (locator: Locator): AsyncGenerator<Locator> {
|
|
for (let index = 0; index < (await locator.count()); index++) {
|
|
yield locator.nth(index)
|
|
}
|
|
}
|
|
|
|
export async function attachScreenshot (name: string, page: Page): Promise<void> {
|
|
await attachment(name, await page.screenshot(), {
|
|
contentType: 'image/png'
|
|
})
|
|
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))])
|
|
}
|
|
|
|
// Check for text in the page
|
|
export const checkTextChunksVisibility = async (page: Page, textChunks: string[]): Promise<void> => {
|
|
for (const textChunk of textChunks) {
|
|
await expect(page.locator(`text=${textChunk}`)).toBeVisible()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resolves the file path for a given file name located in the same directory as the test.
|
|
*
|
|
* @param fileName - name of the file to be resolved
|
|
* @returns - resolved file path
|
|
*/
|
|
|
|
function resolveFilePath (fileName: string): string {
|
|
return path.resolve(__dirname, '.', 'files', fileName)
|
|
}
|
|
|
|
/**
|
|
* Uploads a single file using a file chooser in Playwright.
|
|
*
|
|
* @param page - Playwright Page object
|
|
* @param fileName - name of the file to be uploaded
|
|
* @param fileUploadTestId - test ID of the file input element (default: '@upload-file')
|
|
*/
|
|
export async function uploadFile (page: Page, fileName: string, fileUploadTestId = 'Attached photo'): Promise<void> {
|
|
const uploadFileElement = page.getByText(fileUploadTestId)
|
|
|
|
const [fileChooser] = await Promise.all([page.waitForEvent('filechooser'), uploadFileElement.click()])
|
|
|
|
// Resolve the file path using the 'resolveFilePath' function
|
|
const filePath = resolveFilePath(fileName)
|
|
await fileChooser.setFiles(filePath)
|
|
|
|
// Replace with a more reliable condition for determining when the upload is complete, if possible.
|
|
await page.waitForTimeout(2000)
|
|
}
|
|
|
|
export async function getInviteLink (page: Page): Promise<string | null> {
|
|
const leftSideMenuPage = new LeftSideMenuPage(page)
|
|
await leftSideMenuPage.openProfileMenu()
|
|
await leftSideMenuPage.inviteToWorkspace()
|
|
await leftSideMenuPage.getInviteLink()
|
|
const linkText = await page.locator('.antiPopup .link').textContent()
|
|
expect(linkText).not.toBeNull()
|
|
await leftSideMenuPage.clickOnCloseInvite()
|
|
return linkText
|
|
}
|
|
|
|
export function generateUser (): SignUpData {
|
|
return {
|
|
firstName: faker.person.firstName(),
|
|
lastName: faker.person.lastName(),
|
|
email: faker.internet.email(),
|
|
password: '1234'
|
|
}
|
|
}
|
|
|
|
export async function createAccount (request: APIRequestContext, data: SignUpData): Promise<void> {
|
|
const api: ApiEndpoint = new ApiEndpoint(request)
|
|
await api.createAccount(data.email, data.password, data.firstName, data.lastName)
|
|
}
|
|
|
|
export async function reLogin (page: Page, data: TestData): Promise<void> {
|
|
const loginPage: LoginPage = new LoginPage(page)
|
|
await loginPage.checkingNeedReLogin()
|
|
await (await page.goto(`${PlatformURI}`))?.finished()
|
|
await loginPage.login(data.userName, '1234')
|
|
const swp = new SelectWorkspacePage(page)
|
|
await swp.selectWorkspace(data.workspaceName)
|
|
}
|
|
|
|
export async function createAccountAndWorkspace (page: Page, request: APIRequestContext, data: TestData): Promise<void> {
|
|
const api: ApiEndpoint = new ApiEndpoint(request)
|
|
await api.createAccount(data.userName, '1234', data.firstName, data.lastName)
|
|
await api.createWorkspaceWithLogin(data.workspaceName, data.userName, '1234')
|
|
await reLogin(page, data)
|
|
}
|
|
|
|
export const convertDate = (date: Date): { day: string, month: string, year: string } => {
|
|
return {
|
|
day: date.getDate().toString(),
|
|
month: (date.getMonth() + 1).toString(),
|
|
year: date.getFullYear().toString()
|
|
}
|
|
}
|