mirror of https://github.com/nocodb/nocodb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
2.8 KiB
95 lines
2.8 KiB
import { Locator, Page } from '@playwright/test'; |
|
|
|
type ResponseSelector = (json: any) => boolean; |
|
|
|
export default abstract class BasePage { |
|
readonly rootPage: Page; |
|
|
|
abstract get(args?: any): Locator; |
|
|
|
constructor(rootPage: Page) { |
|
this.rootPage = rootPage; |
|
} |
|
|
|
async verifyToast({ message }: { message: string }) { |
|
await this.rootPage.locator('.ant-message .ant-message-notice-content', { hasText: message }).last().isVisible(); |
|
} |
|
|
|
async waitForResponse({ |
|
// Playwright action that triggers the request i.e locatorSomething.click() |
|
uiAction, |
|
httpMethodsToMatch = [], |
|
requestUrlPathToMatch, |
|
// A function that takes the response body and returns true if the response is the one we are looking for |
|
responseJsonMatcher, |
|
}: { |
|
uiAction: () => Promise<any>; |
|
requestUrlPathToMatch: string; |
|
httpMethodsToMatch?: string[]; |
|
responseJsonMatcher?: ResponseSelector; |
|
}) { |
|
// trigger UI action first |
|
await uiAction(); |
|
// wait for response |
|
const res = await this.rootPage.waitForResponse( |
|
res => |
|
res.url().includes(requestUrlPathToMatch) && |
|
res.status() === 200 && |
|
httpMethodsToMatch.includes(res.request().method()) |
|
); |
|
// handle JSON matcher if provided |
|
let isResJsonMatched = true; |
|
if (responseJsonMatcher) { |
|
try { |
|
isResJsonMatched = responseJsonMatcher(await res.json()); |
|
} catch { |
|
isResJsonMatched = false; |
|
} |
|
} |
|
return isResJsonMatched; |
|
} |
|
|
|
async attachFile({ filePickUIAction, filePath }: { filePickUIAction: Promise<any>; filePath: string[] }) { |
|
const [fileChooser] = await Promise.all([ |
|
// It is important to call waitForEvent before click to set up waiting. |
|
this.rootPage.waitForEvent('filechooser'), |
|
// Opens the file chooser. |
|
filePickUIAction, |
|
]); |
|
await fileChooser.setFiles(filePath); |
|
} |
|
|
|
async downloadAndGetFile({ downloadUIAction }: { downloadUIAction: Promise<any> }) { |
|
const [download] = await Promise.all([ |
|
// It is important to call waitForEvent before click to set up waiting. |
|
this.rootPage.waitForEvent('download'), |
|
// Triggers the download. |
|
downloadUIAction, |
|
]); |
|
// wait for download to complete |
|
if (await download.failure()) { |
|
throw new Error('Download failed'); |
|
} |
|
|
|
const file = await download.createReadStream(); |
|
const data = await new Promise((resolve, reject) => { |
|
let data = ''; |
|
file?.on('data', chunk => (data += chunk)); |
|
file?.on('end', () => resolve(data)); |
|
file?.on('error', reject); |
|
}); |
|
return data as any; |
|
} |
|
|
|
async getClipboardText() { |
|
return await this.rootPage.evaluate(() => navigator.clipboard.readText()); |
|
} |
|
|
|
async os() { |
|
return await this.rootPage.evaluate(() => navigator.platform); |
|
} |
|
|
|
async isMacOs() { |
|
return (await this.os()).includes('Mac'); |
|
} |
|
}
|
|
|