UNPKG

codeceptjs

Version:

Supercharged End 2 End Testing Framework for NodeJS

1,281 lines 530 kB
declare namespace CodeceptJS { /** * AI Helper for CodeceptJS. * * This helper class provides integration with the AI GPT-3.5 or 4 language model for generating responses to questions or prompts within the context of web pages. It allows you to interact with the GPT-3.5 model to obtain intelligent responses based on HTML fragments or general prompts. * This helper should be enabled with any web helpers like Playwright or Puppeteer or WebDriver to ensure the HTML context is available. * * Use it only in development mode. It is recommended to run it only inside pause() mode. * * ## Configuration * * This helper should be configured in codecept.conf.{js|ts} * * * `chunkSize`: (optional, default: 80000) - The maximum number of characters to send to the AI API at once. We split HTML fragments by 8000 chars to not exceed token limit. Increase this value if you use GPT-4. */ class AI { /** * Asks the AI GPT language model a question based on the provided prompt within the context of the current page's HTML. * * ```js * I.askGptOnPage('what does this page do?'); * ``` * @param prompt - The question or prompt to ask the GPT model. * @returns - A Promise that resolves to the generated responses from the GPT model, joined by newlines. */ askGptOnPage(prompt: string): Promise<string>; /** * Asks the AI a question based on the provided prompt within the context of a specific HTML fragment on the current page. * * ```js * I.askGptOnPageFragment('describe features of this screen', '.screen'); * ``` * @param prompt - The question or prompt to ask the GPT-3.5 model. * @param locator - The locator or selector used to identify the HTML fragment on the page. * @returns - A Promise that resolves to the generated response from the GPT model. */ askGptOnPageFragment(prompt: string, locator: string): Promise<string>; /** * Send a general request to AI and return response. * @returns - A Promise that resolves to the generated response from the GPT model. */ askGptGeneralPrompt(prompt: string): Promise<string>; /** * Generates PageObject for current page using AI. * * It saves the PageObject to the output directory. You can review the page object and adjust it as needed and move to pages directory. * Prompt can be customized in a global config file. * * ```js * // create page object for whole page * I.askForPageObject('home'); * * // create page object with extra prompt * I.askForPageObject('home', 'implement signIn(username, password) method'); * * // create page object for a specific element * I.askForPageObject('home', null, '.detail'); * ``` * * Asks for a page object based on the provided page name, locator, and extra prompt. * @param pageName - The name of the page to retrieve the object for. * @param [extraPrompt = null] - An optional extra prompt for additional context or information. * @param [locator = null] - An optional locator to find a specific element on the page. * @returns A promise that resolves to the requested page object. */ askForPageObject(pageName: string, extraPrompt?: string | null, locator?: string | null): Promise<object>; } /** * Helper for managing remote data using REST API. * Uses data generators like [rosie](https://github.com/rosiejs/rosie) or factory girl to create new record. * * By defining a factory you set the rules of how data is generated. * This data will be saved on server via REST API and deleted in the end of a test. * * ## Use Case * * Acceptance tests interact with a websites using UI and real browser. * There is no way to create data for a specific test other than from user interface. * That makes tests slow and fragile. Instead of testing a single feature you need to follow all creation/removal process. * * This helper solves this problem. * Most of web application have API, and it can be used to create and delete test records. * By combining REST API with Factories you can easily create records for tests: * * ```js * I.have('user', { login: 'davert', email: 'davert@mail.com' }); * let id = await I.have('post', { title: 'My first post'}); * I.haveMultiple('comment', 3, {post_id: id}); * ``` * * To make this work you need * * 1. REST API endpoint which allows to perform create / delete requests and * 2. define data generation rules * * ### Setup * * Install [Rosie](https://github.com/rosiejs/rosie) and [Faker](https://www.npmjs.com/package/faker) libraries. * * ```sh * npm i rosie @faker-js/faker --save-dev * ``` * * Create a factory file for a resource. * * See the example for Posts factories: * * ```js * // tests/factories/posts.js * * const { Factory } = require('rosie'); * const { faker } = require('@faker-js/faker'); * * module.exports = new Factory() * // no need to set id, it will be set by REST API * .attr('author', () => faker.person.findName()) * .attr('title', () => faker.lorem.sentence()) * .attr('body', () => faker.lorem.paragraph()); * ``` * For more options see [rosie documentation](https://github.com/rosiejs/rosie). * * Then configure ApiDataHelper to match factories and REST API: * ### Configuration * * ApiDataFactory has following config options: * * * `endpoint`: base URL for the API to send requests to. * * `cleanup` (default: true): should inserted records be deleted up after tests * * `factories`: list of defined factories * * `returnId` (default: false): return id instead of a complete response when creating items. * * `headers`: list of headers * * `REST`: configuration for REST requests * * See the example: * * ```js * ApiDataFactory: { * endpoint: "http://user.com/api", * cleanup: true, * headers: { * 'Content-Type': 'application/json', * 'Accept': 'application/json', * }, * factories: { * post: { * uri: "/posts", * factory: "./factories/post", * }, * comment: { * factory: "./factories/comment", * create: { post: "/comments/create" }, * delete: { post: "/comments/delete/{id}" }, * fetchId: (data) => data.result.id * } * } * } * ``` * It is required to set REST API `endpoint` which is the baseURL for all API requests. * Factory file is expected to be passed via `factory` option. * * This Helper uses [REST](http://codecept.io/helpers/REST/) helper and accepts its configuration in "REST" section. * For instance, to set timeout you should add: * * ```js * "ApiDataFactory": { * "REST": { * "timeout": "100000", * } * } * ``` * * ### Requests * * By default to create a record ApiDataFactory will use endpoint and plural factory name: * * * create: `POST {endpoint}/{resource} data` * * delete: `DELETE {endpoint}/{resource}/id` * * Example (`endpoint`: `http://app.com/api`): * * * create: POST request to `http://app.com/api/users` * * delete: DELETE request to `http://app.com/api/users/1` * * This behavior can be configured with following options: * * * `uri`: set different resource uri. Example: `uri: account` => `http://app.com/api/account`. * * `create`: override create options. Expected format: `{ method: uri }`. Example: `{ "post": "/users/create" }` * * `delete`: override delete options. Expected format: `{ method: uri }`. Example: `{ "post": "/users/delete/{id}" }` * * Requests can also be overridden with a function which returns [axois request config](https://github.com/axios/axios#request-config). * * ```js * create: (data) => ({ method: 'post', url: '/posts', data }), * delete: (id) => ({ method: 'delete', url: '/posts', data: { id } }) * * ``` * * Requests can be updated on the fly by using `onRequest` function. For instance, you can pass in current session from a cookie. * * ```js * onRequest: async (request) => { * // using global codeceptjs instance * let cookie = await codeceptjs.container.helpers('WebDriver').grabCookie('session'); * request.headers = { Cookie: `session=${cookie.value}` }; * } * ``` * * ### Responses * * By default `I.have()` returns a promise with a created data: * * ```js * let client = await I.have('client'); * ``` * * Ids of created records are collected and used in the end of a test for the cleanup. * If you need to receive `id` instead of full response enable `returnId` in a helper config: * * ```js * // returnId: false * let clientId = await I.have('client'); * // clientId == 1 * * // returnId: true * let clientId = await I.have('client'); * // client == { name: 'John', email: 'john@snow.com' } * ``` * * By default `id` property of response is taken. This behavior can be changed by setting `fetchId` function in a factory config. * * * ```js * factories: { * post: { * uri: "/posts", * factory: "./factories/post", * fetchId: (data) => data.result.posts[0].id * } * } * ``` * * * ## Methods */ class ApiDataFactory { /** * Generates a new record using factory and saves API request to store it. * * ```js * // create a user * I.have('user'); * // create user with defined email * // and receive it when inside async function * const user = await I.have('user', { email: 'user@user.com'}); * // create a user with options that will not be included in the final request * I.have('user', { }, { age: 33, height: 55 }) * ``` * @param factory - factory to use * @param [params] - predefined parameters * @param [options] - options for programmatically generate the attributes */ have(factory: any, params?: any, options?: any): Promise<any>; /** * Generates bunch of records and saves multiple API requests to store them. * * ```js * // create 3 posts * I.haveMultiple('post', 3); * * // create 3 posts by one author * I.haveMultiple('post', 3, { author: 'davert' }); * * // create 3 posts by one author with options * I.haveMultiple('post', 3, { author: 'davert' }, { publish_date: '01.01.1997' }); * ``` */ haveMultiple(factory: any, times: any, params?: any, options?: any): void; /** * Executes request to create a record in API. * Can be replaced from a in custom helper. */ _requestCreate(factory: any, data: any): void; /** * Executes request to delete a record in API * Can be replaced from a custom helper. */ _requestDelete(factory: any, id: any): void; } /** * Appium Special Methods for Mobile only */ class Appium extends WebDriver { /** * Execute code only on iOS * * ```js * I.runOnIOS(() => { * I.click('//UIAApplication[1]/UIAWindow[1]/UIAButton[1]'); * I.see('Hi, IOS', '~welcome'); * }); * ``` * * Additional filter can be applied by checking for capabilities. * For instance, this code will be executed only on iPhone 5s: * * * ```js * I.runOnIOS({deviceName: 'iPhone 5s'},() => { * // ... * }); * ``` * * Also capabilities can be checked by a function. * * ```js * I.runOnAndroid((caps) => { * // caps is current config of desiredCapabiliites * return caps.platformVersion >= 6 * },() => { * // ... * }); * ``` */ runOnIOS(caps: any, fn: any): void; /** * Execute code only on Android * * ```js * I.runOnAndroid(() => { * I.click('io.selendroid.testapp:id/buttonTest'); * }); * ``` * * Additional filter can be applied by checking for capabilities. * For instance, this code will be executed only on Android 6.0: * * * ```js * I.runOnAndroid({platformVersion: '6.0'},() => { * // ... * }); * ``` * * Also capabilities can be checked by a function. * In this case, code will be executed only on Android >= 6. * * ```js * I.runOnAndroid((caps) => { * // caps is current config of desiredCapabiliites * return caps.platformVersion >= 6 * },() => { * // ... * }); * ``` */ runOnAndroid(caps: any, fn: any): void; /** * Execute code only in Web mode. * * ```js * I.runInWeb(() => { * I.waitForElement('#data'); * I.seeInCurrentUrl('/data'); * }); * ``` */ runInWeb(): void; /** * Returns app installation status. * * ```js * I.checkIfAppIsInstalled("com.example.android.apis"); * ``` * @param bundleId - String ID of bundled app * @returns Appium: support only Android */ checkIfAppIsInstalled(bundleId: string): Promise<boolean>; /** * Check if an app is installed. * * ```js * I.seeAppIsInstalled("com.example.android.apis"); * ``` * @param bundleId - String ID of bundled app * @returns Appium: support only Android */ seeAppIsInstalled(bundleId: string): Promise<void>; /** * Check if an app is not installed. * * ```js * I.seeAppIsNotInstalled("com.example.android.apis"); * ``` * @param bundleId - String ID of bundled app * @returns Appium: support only Android */ seeAppIsNotInstalled(bundleId: string): Promise<void>; /** * Install an app on device. * * ```js * I.installApp('/path/to/file.apk'); * ``` * @param path - path to apk file * @returns Appium: support only Android */ installApp(path: string): Promise<void>; /** * Remove an app from the device. * * ```js * I.removeApp('appName', 'com.example.android.apis'); * ``` * * Appium: support only Android * @param [bundleId] - ID of bundle */ removeApp(appId: string, bundleId?: string): void; /** * Reset the currently running app for current session. * * ```js * I.resetApp(); * ``` */ resetApp(): void; /** * Check current activity on an Android device. * * ```js * I.seeCurrentActivityIs(".HomeScreenActivity") * ``` * @returns Appium: support only Android */ seeCurrentActivityIs(currentActivity: string): Promise<void>; /** * Check whether the device is locked. * * ```js * I.seeDeviceIsLocked(); * ``` * @returns Appium: support only Android */ seeDeviceIsLocked(): Promise<void>; /** * Check whether the device is not locked. * * ```js * I.seeDeviceIsUnlocked(); * ``` * @returns Appium: support only Android */ seeDeviceIsUnlocked(): Promise<void>; /** * Check the device orientation * * ```js * I.seeOrientationIs('PORTRAIT'); * I.seeOrientationIs('LANDSCAPE') * ``` * @param orientation - LANDSCAPE or PORTRAIT * * Appium: support Android and iOS */ seeOrientationIs(orientation: 'LANDSCAPE' | 'PORTRAIT'): Promise<void>; /** * Set a device orientation. Will fail, if app will not set orientation * * ```js * I.setOrientation('PORTRAIT'); * I.setOrientation('LANDSCAPE') * ``` * @param orientation - LANDSCAPE or PORTRAIT * * Appium: support Android and iOS */ setOrientation(orientation: 'LANDSCAPE' | 'PORTRAIT'): void; /** * Get list of all available contexts * * ``` * let contexts = await I.grabAllContexts(); * ``` * @returns Appium: support Android and iOS */ grabAllContexts(): Promise<string[]>; /** * Retrieve current context * * ```js * let context = await I.grabContext(); * ``` * @returns Appium: support Android and iOS */ grabContext(): Promise<string | null>; /** * Get current device activity. * * ```js * let activity = await I.grabCurrentActivity(); * ``` * @returns Appium: support only Android */ grabCurrentActivity(): Promise<string>; /** * Get information about the current network connection (Data/WIFI/Airplane). * The actual server value will be a number. However WebdriverIO additional * properties to the response object to allow easier assertions. * * ```js * let con = await I.grabNetworkConnection(); * ``` * @returns Appium: support only Android */ grabNetworkConnection(): Promise<{}>; /** * Get current orientation. * * ```js * let orientation = await I.grabOrientation(); * ``` * @returns Appium: support Android and iOS */ grabOrientation(): Promise<string>; /** * Get all the currently specified settings. * * ```js * let settings = await I.grabSettings(); * ``` * @returns Appium: support Android and iOS */ grabSettings(): Promise<string>; /** * Switch to the specified context. * @param context - the context to switch to */ switchToContext(context: any): void; /** * Switches to web context. * If no context is provided switches to the first detected web context * * ```js * // switch to first web context * I.switchToWeb(); * * // or set the context explicitly * I.switchToWeb('WEBVIEW_io.selendroid.testapp'); * ``` */ switchToWeb(context?: string): Promise<void>; /** * Switches to native context. * By default switches to NATIVE_APP context unless other specified. * * ```js * I.switchToNative(); * * // or set context explicitly * I.switchToNative('SOME_OTHER_CONTEXT'); * ``` */ switchToNative(context?: any): Promise<void>; /** * Start an arbitrary Android activity during a session. * * ```js * I.startActivity('io.selendroid.testapp', '.RegisterUserActivity'); * ``` * * Appium: support only Android */ startActivity(appPackage: string, appActivity: string): Promise<void>; /** * Set network connection mode. * * * airplane mode * * wifi mode * * data data * * ```js * I.setNetworkConnection(0) // airplane mode off, wifi off, data off * I.setNetworkConnection(1) // airplane mode on, wifi off, data off * I.setNetworkConnection(2) // airplane mode off, wifi on, data off * I.setNetworkConnection(4) // airplane mode off, wifi off, data on * I.setNetworkConnection(6) // airplane mode off, wifi on, data on * ``` * See corresponding [webdriverio reference](https://webdriver.io/docs/api/chromium/#setnetworkconnection). * * Appium: support only Android * @param value - The network connection mode bitmask */ setNetworkConnection(value: number): Promise<number>; /** * Update the current setting on the device * * ```js * I.setSettings({cyberdelia: 'open'}); * ``` * @param settings - object * * Appium: support Android and iOS */ setSettings(settings: any): void; /** * Hide the keyboard. * * ```js * // taps outside to hide keyboard per default * I.hideDeviceKeyboard(); * ``` * * Appium: support Android and iOS */ hideDeviceKeyboard(): void; /** * Send a key event to the device. * List of keys: https://developer.android.com/reference/android/view/KeyEvent.html * * ```js * I.sendDeviceKeyEvent(3); * ``` * @param keyValue - Device specific key value * @returns Appium: support only Android */ sendDeviceKeyEvent(keyValue: number): Promise<void>; /** * Open the notifications panel on the device. * * ```js * I.openNotifications(); * ``` * @returns Appium: support only Android */ openNotifications(): Promise<void>; /** * The Touch Action API provides the basis of all gestures that can be * automated in Appium. At its core is the ability to chain together ad hoc * individual actions, which will then be applied to an element in the * application on the device. * [See complete documentation](http://webdriver.io/api/mobile/touchAction.html) * * ```js * I.makeTouchAction("~buttonStartWebviewCD", 'tap'); * ``` * @returns Appium: support Android and iOS */ makeTouchAction(): Promise<void>; /** * Taps on element. * * ```js * I.tap("~buttonStartWebviewCD"); * ``` * * Shortcut for `makeTouchAction` */ tap(locator: any): Promise<void>; /** * Perform a swipe on the screen or an element. * * ```js * let locator = "#io.selendroid.testapp:id/LinearLayout1"; * I.swipe(locator, 800, 1200, 1000); * ``` * * [See complete reference](http://webdriver.io/api/mobile/swipe.html) * @param [speed = 1000] - (optional), 1000 by default * @returns Appium: support Android and iOS */ swipe(locator: CodeceptJS.LocatorOrString, xoffset: number, yoffset: number, speed?: number): Promise<void>; /** * Perform a swipe on the screen. * * ```js * I.performSwipe({ x: 300, y: 100 }, { x: 200, y: 100 }); * ``` * @param to - Appium: support Android and iOS */ performSwipe(from: any, to: any): void; /** * Perform a swipe down on an element. * * ```js * let locator = "#io.selendroid.testapp:id/LinearLayout1"; * I.swipeDown(locator); // simple swipe * I.swipeDown(locator, 500); // set speed * I.swipeDown(locator, 1200, 1000); // set offset and speed * ``` * @param [yoffset = 1000] - (optional) * @param [speed = 1000] - (optional), 1000 by default * @returns Appium: support Android and iOS */ swipeDown(locator: CodeceptJS.LocatorOrString, yoffset?: number, speed?: number): Promise<void>; /** * Perform a swipe left on an element. * * ```js * let locator = "#io.selendroid.testapp:id/LinearLayout1"; * I.swipeLeft(locator); // simple swipe * I.swipeLeft(locator, 500); // set speed * I.swipeLeft(locator, 1200, 1000); // set offset and speed * ``` * @param [xoffset = 1000] - (optional) * @param [speed = 1000] - (optional), 1000 by default * @returns Appium: support Android and iOS */ swipeLeft(locator: CodeceptJS.LocatorOrString, xoffset?: number, speed?: number): Promise<void>; /** * Perform a swipe right on an element. * * ```js * let locator = "#io.selendroid.testapp:id/LinearLayout1"; * I.swipeRight(locator); // simple swipe * I.swipeRight(locator, 500); // set speed * I.swipeRight(locator, 1200, 1000); // set offset and speed * ``` * @param [xoffset = 1000] - (optional) * @param [speed = 1000] - (optional), 1000 by default * @returns Appium: support Android and iOS */ swipeRight(locator: CodeceptJS.LocatorOrString, xoffset?: number, speed?: number): Promise<void>; /** * Perform a swipe up on an element. * * ```js * let locator = "#io.selendroid.testapp:id/LinearLayout1"; * I.swipeUp(locator); // simple swipe * I.swipeUp(locator, 500); // set speed * I.swipeUp(locator, 1200, 1000); // set offset and speed * ``` * @param [yoffset = 1000] - (optional) * @param [speed = 1000] - (optional), 1000 by default * @returns Appium: support Android and iOS */ swipeUp(locator: CodeceptJS.LocatorOrString, yoffset?: number, speed?: number): Promise<void>; /** * Perform a swipe in selected direction on an element to searchable element. * * ```js * I.swipeTo( * "android.widget.CheckBox", // searchable element * "//android.widget.ScrollView/android.widget.LinearLayout", // scroll element * "up", // direction * 30, * 100, * 500); * ``` * @returns Appium: support Android and iOS */ swipeTo(searchableLocator: string, scrollLocator: string, direction: string, timeout: number, offset: number, speed: number): Promise<void>; /** * Performs a specific touch action. * The action object need to contain the action name, x/y coordinates * * ```js * I.touchPerform([{ * action: 'press', * options: { * x: 100, * y: 200 * } * }, {action: 'release'}]) * * I.touchPerform([{ * action: 'tap', * options: { * element: '1', // json web element was queried before * x: 10, // x offset * y: 20, // y offset * count: 1 // number of touches * } * }]); * ``` * * Appium: support Android and iOS * @param actions - Array of touch actions */ touchPerform(actions: any[]): void; /** * Pulls a file from the device. * * ```js * I.pullFile('/storage/emulated/0/DCIM/logo.png', 'my/path'); * // save file to output dir * I.pullFile('/storage/emulated/0/DCIM/logo.png', output_dir); * ``` * @returns Appium: support Android and iOS */ pullFile(path: string, dest: string): Promise<string>; /** * Perform a shake action on the device. * * ```js * I.shakeDevice(); * ``` * @returns Appium: support only iOS */ shakeDevice(): Promise<void>; /** * Perform a rotation gesture centered on the specified element. * * ```js * I.rotate(120, 120) * ``` * * See corresponding [webdriverio reference](http://webdriver.io/api/mobile/rotate.html). * @returns Appium: support only iOS */ rotate(): Promise<void>; /** * Set immediate value in app. * * See corresponding [webdriverio reference](http://webdriver.io/api/mobile/setImmediateValue.html). * @returns Appium: support only iOS */ setImmediateValue(): Promise<void>; /** * Simulate Touch ID with either valid (match == true) or invalid (match == false) fingerprint. * * ```js * I.touchId(); // simulates valid fingerprint * I.touchId(true); // simulates valid fingerprint * I.touchId(false); // simulates invalid fingerprint * ``` * @returns Appium: support only iOS * TODO: not tested */ simulateTouchId(): Promise<void>; /** * Close the given application. * * ```js * I.closeApp(); * ``` * @returns Appium: support both Android and iOS */ closeApp(): Promise<void>; /** * Appends text to a input field or textarea. * Field is located by name, label, CSS or XPath * * ```js * I.appendField('#myTextField', 'appended'); * // typing secret * I.appendField('password', secret('123456')); * ``` * @param field - located by label|name|CSS|XPath|strict locator * @param value - text value to append. * @returns automatically synchronized promise through #recorder */ appendField(field: CodeceptJS.LocatorOrString, value: string): void; /** * Selects a checkbox or radio button. * Element is located by label or name or CSS or XPath. * * The second parameter is a context (CSS or XPath locator) to narrow the search. * * ```js * I.checkOption('#agree'); * I.checkOption('I Agree to Terms and Conditions'); * I.checkOption('agree', '//form'); * ``` * @param field - checkbox located by label | name | CSS | XPath | strict locator. * @param [context = null] - (optional, `null` by default) element located by CSS | XPath | strict locator. * @returns automatically synchronized promise through #recorder */ checkOption(field: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString): void; /** * Perform a click on a link or a button, given by a locator. * If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. * For buttons, the "value" attribute, "name" attribute, and inner text are searched. For links, the link text is searched. * For images, the "alt" attribute and inner text of any parent links are searched. * * The second parameter is a context (CSS or XPath locator) to narrow the search. * * ```js * // simple link * I.click('Logout'); * // button of form * I.click('Submit'); * // CSS button * I.click('#form input[type=submit]'); * // XPath * I.click('//form/*[@type=submit]'); * // link in context * I.click('Logout', '#nav'); * // using strict locator * I.click({css: 'nav a.login'}); * ``` * @param locator - clickable link or button located by text, or any element located by CSS|XPath|strict locator. * @param [context = null] - (optional, `null` by default) element to search in CSS|XPath|Strict locator. * @returns automatically synchronized promise through #recorder */ click(locator: CodeceptJS.LocatorOrString, context?: CodeceptJS.LocatorOrString | null): void; /** * Verifies that the specified checkbox is not checked. * * ```js * I.dontSeeCheckboxIsChecked('#agree'); // located by ID * I.dontSeeCheckboxIsChecked('I agree to terms'); // located by label * I.dontSeeCheckboxIsChecked('agree'); // located by name * ``` * @param field - located by label|name|CSS|XPath|strict locator. * @returns automatically synchronized promise through #recorder */ dontSeeCheckboxIsChecked(field: CodeceptJS.LocatorOrString): void; /** * Opposite to `seeElement`. Checks that element is not visible (or in DOM) * * ```js * I.dontSeeElement('.modal'); // modal is not shown * ``` * @param locator - located by CSS|XPath|Strict locator. * @returns automatically synchronized promise through #recorder */ dontSeeElement(locator: CodeceptJS.LocatorOrString): void; /** * Checks that value of input field or textarea doesn't equal to given value * Opposite to `seeInField`. * * ```js * I.dontSeeInField('email', 'user@user.com'); // field by name * I.dontSeeInField({ css: 'form input.email' }, 'user@user.com'); // field by CSS * ``` * @param field - located by label|name|CSS|XPath|strict locator. * @param value - value to check. * @returns automatically synchronized promise through #recorder */ dontSeeInField(field: CodeceptJS.LocatorOrString, value: CodeceptJS.StringOrSecret): void; /** * Opposite to `see`. Checks that a text is not present on a page. * Use context parameter to narrow down the search. * * ```js * I.dontSee('Login'); // assume we are already logged in. * I.dontSee('Login', '.nav'); // no login inside .nav element * ``` * @param text - which is not present. * @param [context = null] - (optional) element located by CSS|XPath|strict locator in which to perfrom search. * @returns automatically synchronized promise through #recorder */ dontSee(text: string, context?: CodeceptJS.LocatorOrString): void; /** * Fills a text field or textarea, after clearing its value, with the given string. * Field is located by name, label, CSS, or XPath. * * ```js * // by label * I.fillField('Email', 'hello@world.com'); * // by name * I.fillField('password', secret('123456')); * // by CSS * I.fillField('form#login input[name=username]', 'John'); * // or by strict locator * I.fillField({css: 'form#login input[name=username]'}, 'John'); * ``` * @param field - located by label|name|CSS|XPath|strict locator. * @param value - text value to fill. * @returns automatically synchronized promise through #recorder */ fillField(field: CodeceptJS.LocatorOrString, value: CodeceptJS.StringOrSecret): void; /** * Retrieves all texts from an element located by CSS or XPath and returns it to test. * Resumes test execution, so **should be used inside async with `await`** operator. * * ```js * let pins = await I.grabTextFromAll('#pin li'); * ``` * @param locator - element located by CSS|XPath|strict locator. * @returns attribute value */ grabTextFromAll(locator: CodeceptJS.LocatorOrString): Promise<string[]>; /** * Retrieves a text from an element located by CSS or XPath and returns it to test. * Resumes test execution, so **should be used inside async with `await`** operator. * * ```js * let pin = await I.grabTextFrom('#pin'); * ``` * If multiple elements found returns first element. * @param locator - element located by CSS|XPath|strict locator. * @returns attribute value */ grabTextFrom(locator: CodeceptJS.LocatorOrString): Promise<string>; /** * Grab number of visible elements by locator. * Resumes test execution, so **should be used inside async function with `await`** operator. * * ```js * let numOfElements = await I.grabNumberOfVisibleElements('p'); * ``` * @param locator - located by CSS|XPath|strict locator. * @returns number of visible elements */ grabNumberOfVisibleElements(locator: CodeceptJS.LocatorOrString): Promise<number>; /** * Can be used for apps only with several values ("contentDescription", "text", "className", "resourceId") * * Retrieves an attribute from an element located by CSS or XPath and returns it to test. * Resumes test execution, so **should be used inside async with `await`** operator. * If more than one element is found - attribute of first element is returned. * * ```js * let hint = await I.grabAttributeFrom('#tooltip', 'title'); * ``` * @param locator - element located by CSS|XPath|strict locator. * @param attr - attribute name. * @returns attribute value */ grabAttributeFrom(locator: CodeceptJS.LocatorOrString, attr: string): Promise<string>; /** * Can be used for apps only with several values ("contentDescription", "text", "className", "resourceId") * Retrieves an array of attributes from elements located by CSS or XPath and returns it to test. * Resumes test execution, so **should be used inside async with `await`** operator. * * ```js * let hints = await I.grabAttributeFromAll('.tooltip', 'title'); * ``` * @param locator - element located by CSS|XPath|strict locator. * @param attr - attribute name. * @returns attribute value */ grabAttributeFromAll(locator: CodeceptJS.LocatorOrString, attr: string): Promise<string[]>; /** * Retrieves an array of value from a form located by CSS or XPath and returns it to test. * Resumes test execution, so **should be used inside async function with `await`** operator. * * ```js * let inputs = await I.grabValueFromAll('//form/input'); * ``` * @param locator - field located by label|name|CSS|XPath|strict locator. * @returns attribute value */ grabValueFromAll(locator: CodeceptJS.LocatorOrString): Promise<string[]>; /** * Retrieves a value from a form element located by CSS or XPath and returns it to test. * Resumes test execution, so **should be used inside async function with `await`** operator. * If more than one element is found - value of first element is returned. * * ```js * let email = await I.grabValueFrom('input[name=email]'); * ``` * @param locator - field located by label|name|CSS|XPath|strict locator. * @returns attribute value */ grabValueFrom(locator: CodeceptJS.LocatorOrString): Promise<string>; /** * Saves a screenshot to ouput folder (set in codecept.conf.ts or codecept.conf.js). * Filename is relative to output folder. * * ```js * I.saveScreenshot('debug.png'); * ``` * @param fileName - file name to save. */ saveScreenshot(fileName: string): Promise<void>; /** * Scroll element into viewport. * * ```js * I.scrollIntoView('#submit'); * I.scrollIntoView('#submit', true); * I.scrollIntoView('#submit', { behavior: "smooth", block: "center", inline: "center" }); * ``` * @param locator - located by CSS|XPath|strict locator. * @param scrollIntoViewOptions - either alignToTop=true|false or scrollIntoViewOptions. See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView. * @returns automatically synchronized promise through #recorder * * * Supported only for web testing */ scrollIntoView(locator: LocatorOrString, scrollIntoViewOptions: ScrollIntoViewOptions | boolean): void; /** * Verifies that the specified checkbox is checked. * * ```js * I.seeCheckboxIsChecked('Agree'); * I.seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms * I.seeCheckboxIsChecked({css: '#signup_form input[type=checkbox]'}); * ``` * @param field - located by label|name|CSS|XPath|strict locator. * @returns automatically synchronized promise through #recorder */ seeCheckboxIsChecked(field: CodeceptJS.LocatorOrString): void; /** * Checks that a given Element is visible * Element is located by CSS or XPath. * * ```js * I.seeElement('#modal'); * ``` * @param locator - located by CSS|XPath|strict locator. * @returns automatically synchronized promise through #recorder */ seeElement(locator: CodeceptJS.LocatorOrString): void; /** * Checks that the given input field or textarea equals to given value. * For fuzzy locators, fields are matched by label text, the "name" attribute, CSS, and XPath. * * ```js * I.seeInField('Username', 'davert'); * I.seeInField({css: 'form textarea'},'Type your comment here'); * I.seeInField('form input[type=hidden]','hidden_value'); * I.seeInField('#searchform input','Search'); * ``` * @param field - located by label|name|CSS|XPath|strict locator. * @param value - value to check. * @returns automatically synchronized promise through #recorder */ seeInField(field: CodeceptJS.LocatorOrString, value: CodeceptJS.StringOrSecret): void; /** * Checks that a page contains a visible text. * Use context parameter to narrow down the search. * * ```js * I.see('Welcome'); // text welcome on a page * I.see('Welcome', '.content'); // text inside .content div * I.see('Register', {css: 'form.register'}); // use strict locator * ``` * @param text - expected on page. * @param [context = null] - (optional, `null` by default) element located by CSS|Xpath|strict locator in which to search for text. * @returns automatically synchronized promise through #recorder */ see(text: string, context?: CodeceptJS.LocatorOrString): void; /** * Selects an option in a drop-down select. * Field is searched by label | name | CSS | XPath. * Option is selected by visible text or by value. * * ```js * I.selectOption('Choose Plan', 'Monthly'); // select by label * I.selectOption('subscription', 'Monthly'); // match option by text * I.selectOption('subscription', '0'); // or by value * I.selectOption('//form/select[@name=account]','Premium'); * I.selectOption('form select[name=account]', 'Premium'); * I.selectOption({css: 'form select[name=account]'}, 'Premium'); * ``` * * Provide an array for the second argument to select multiple options. * * ```js * I.selectOption('Which OS do you use?', ['Android', 'iOS']); * ``` * @param select - field located by label|name|CSS|XPath|strict locator. * @param option - visible text or value of option. * @returns automatically synchronized promise through #recorder * * * Supported only for web testing */ selectOption(select: LocatorOrString, option: string | any[]): void; /** * Waits for element to be present on page (by default waits for 1sec). * Element can be located by CSS or XPath. * * ```js * I.waitForElement('.btn.continue'); * I.waitForElement('.btn.continue', 5); // wait for 5 secs * ``` * @param locator - element located by CSS|XPath|strict locator. * @param [sec = null] - (optional, `1` by default) time in seconds to wait * @returns automatically synchronized promise through #recorder */ waitForElement(locator: CodeceptJS.LocatorOrString, sec?: number): void; /** * Waits for an element to become visible on a page (by default waits for 1sec). * Element can be located by CSS or XPath. * * ```js * I.waitForVisible('#popup'); * ``` * @param locator - element located by CSS|XPath|strict locator. * @param [sec = 1] - (optional, `1` by default) time in seconds to wait * @returns automatically synchronized promise through #recorder */ waitForVisible(locator: CodeceptJS.LocatorOrString, sec?: number): void; /** * Waits for an element to be removed or become invisible on a page (by default waits for 1sec). * Element can be located by CSS or XPath. * * ```js * I.waitForInvisible('#popup'); * ``` * @param locator - element located by CSS|XPath|strict locator. * @param [sec = 1] - (optional, `1` by default) time in seconds to wait * @returns automatically synchronized promise through #recorder */ waitForInvisible(locator: CodeceptJS.LocatorOrString, sec?: number): void; /** * Waits for a text to appear (by default waits for 1sec). * Element can be located by CSS or XPath. * Narrow down search results by providing context. * * ```js * I.waitForText('Thank you, form has been submitted'); * I.waitForText('Thank you, form has been submitted', 5, '#modal'); * ``` * @param text - to wait for. * @param [sec = 1] - (optional, `1` by default) time in seconds to wait * @param [context = null] - (optional) element located by CSS|XPath|strict locator. * @returns automatically synchronized promise through #recorder */ waitForText(text: string, sec?: number, context?: CodeceptJS.LocatorOrString): void; } /** * Helper for testing filesystem. * Can be easily used to check file structures: * * ```js * I.amInPath('test'); * I.seeFile('codecept.js'); * I.seeInThisFile('FileSystem'); * I.dontSeeInThisFile("WebDriver"); * ``` * * ## Configuration * * Enable helper in config file: * * ```js * helpers: { * FileSystem: {}, * } * ``` * * ## Methods */ class FileSystem { /** * Enters a directory In local filesystem. * Starts from a current directory */ amInPath(openPath: string): void; /** * Writes text to file */ writeToFile(name: string, text: string): void; /** * Checks that file exists */ seeFile(name: string): void; /** * Waits for the file to be present in the current directory. * * ```js * I.handleDownloads('downloads/largeFilesName.txt'); * I.click('Download large File'); * I.amInPath('output/downloads'); * I.waitForFile('largeFilesName.txt', 10); // wait 10 seconds for file * ``` * @param [sec = 1] - seconds to wait */ waitForFile(name: string, sec?: number): void; /** * Checks that file with a name including given text exists in the current directory. * * ```js * I.handleDownloads(); * I.click('Download as PDF'); * I.amInPath('output/downloads'); * I.seeFileNameMatching('.pdf'); * ``` */ seeFileNameMatching(text: string): void; /** * Checks that file found by `seeFile` includes a text. */ seeInThisFile(text: string, encoding?: string): void; /** * Checks that file found by `seeFile` doesn't include text. */ dontSeeInThisFile(text: string, encoding?: string): void; /** * Checks that contents of file found by `seeFile` equal to text. */ seeFileContentsEqual(text: string, encoding?: string): void; /** * Checks that contents of the file found by `seeFile` equal to contents of the file at `pathToReferenceFile`. */ seeFileContentsEqualReferenceFile(pathToReferenceFile: string, encoding?: string, encodingReference?