मुख्य सामग्री पर जाएं

कस्टम कमांड्स

यदि आप browser इंस्टेंस को अपने स्वयं के कमांड्स के सेट के साथ विस्तारित करना चाहते हैं, तो ब्राउज़र मेथड addCommand आपके लिए उपलब्ध है। आप अपनी कमांड को एसिंक्रोनस तरीके से लिख सकते हैं, जैसे आपके स्पेक्स में करते हैं।

पैरामीटर्स

कमांड नाम

एक नाम जो कमांड को परिभाषित करता है और ब्राउज़र या एलिमेंट स्कोप से जुड़ जाएगा।

प्रकार: String

कस्टम फंक्शन

एक फंक्शन जो कमांड के कॉल होने पर निष्पादित होता है। this स्कोप या तो WebdriverIO.Browser या WebdriverIO.Element होता है, इस बात पर निर्भर करता है कि कमांड ब्राउज़र स्कोप से जुड़ी है या एलिमेंट स्कोप से।

प्रकार: Function

टारगेट स्कोप

यह फ्लैग निर्धारित करता है कि कमांड को ब्राउज़र स्कोप से जोड़ना है या एलिमेंट स्कोप से। यदि true पर सेट है, तो कमांड एक एलिमेंट कमांड होगी।

प्रकार: Boolean
डिफ़ॉल्ट: false

उदाहरण

यह उदाहरण दिखाता है कि कैसे एक नई कमांड जोड़ें जो वर्तमान URL और शीर्षक को एक परिणाम के रूप में वापस करती है। स्कोप (this) एक WebdriverIO.Browser ऑब्जेक्ट है।

browser.addCommand('getUrlAndTitle', async function (customVar) {
// `this` refers to the `browser` scope
return {
url: await this.getUrl(),
title: await this.getTitle(),
customVar: customVar
}
})

इसके अतिरिक्त, आप एलिमेंट इंस्टेंस को अपने स्वयं के कमांड्स के सेट के साथ विस्तारित कर सकते हैं, अंतिम आर्गुमेंट के रूप में true पास करके। इस मामले में स्कोप (this) एक WebdriverIO.Element ऑब्जेक्ट है।

browser.addCommand("waitAndClick", async function () {
// `this` is return value of $(selector)
await this.waitForDisplayed()
await this.click()
}, true)

कस्टम कमांड्स आपको अक्सर उपयोग किए जाने वाले कमांड्स के विशिष्ट अनुक्रम को एक ही कॉल के रूप में बंडल करने का अवसर देती हैं। आप अपनी टेस्ट सूट में किसी भी बिंदु पर कस्टम कमांड्स को परिभाषित कर सकते हैं; बस यह सुनिश्चित करें कि कमांड को इसके पहले उपयोग से पहले परिभाषित किया गया है। (आपके wdio.conf.js में before हुक इन्हें बनाने के लिए एक अच्छी जगह है।)

एक बार परिभाषित होने के बाद, आप उन्हें निम्नानुसार उपयोग कर सकते हैं:

it('should use my custom command', async () => {
await browser.url('http://www.github.com')
const result = await browser.getUrlAndTitle('foobar')

assert.strictEqual(result.url, 'https://github.com/')
assert.strictEqual(result.title, 'GitHub · Where software is built')
assert.strictEqual(result.customVar, 'foobar')
})

नोट: यदि आप browser स्कोप के लिए एक कस्टम कमांड रजिस्टर करते हैं, तो कमांड एलिमेंट्स के लिए एक्सेसिबल नहीं होगी। इसी तरह, यदि आप एलिमेंट स्कोप के लिए एक कमांड रजिस्टर करते हैं, तो यह browser स्कोप में एक्सेसिबल नहीं होगी:

browser.addCommand("myCustomBrowserCommand", () => { return 1 })
const elem = await $('body')
console.log(typeof browser.myCustomBrowserCommand) // outputs "function"
console.log(typeof elem.myCustomBrowserCommand()) // outputs "undefined"

browser.addCommand("myCustomElementCommand", () => { return 1 }, true)
const elem2 = await $('body')
console.log(typeof browser.myCustomElementCommand) // outputs "undefined"
console.log(await elem2.myCustomElementCommand('foobar')) // outputs "1"

const elem3 = await $('body')
elem3.addCommand("myCustomElementCommand2", () => { return 2 })
console.log(typeof browser.myCustomElementCommand2) // outputs "undefined"
console.log(await elem3.myCustomElementCommand2('foobar')) // outputs "2"

नोट: यदि आपको एक कस्टम कमांड को चेन करने की आवश्यकता है, तो कमांड $ के साथ समाप्त होनी चाहिए,

browser.addCommand("user$", (locator) => { return ele })
browser.addCommand("user$", (locator) => { return ele }, true)
await browser.user$('foo').user$('bar').click()

सावधान रहें कि browser स्कोप को बहुत अधिक कस्टम कमांड्स से ओवरलोड न करें।

हम पेज ऑब्जेक्ट्स में कस्टम लॉजिक को परिभाषित करने की सलाह देते हैं, ताकि वे एक विशिष्ट पेज से बाध्य हों।

मल्टीरिमोट

addCommand मल्टीरिमोट के लिए एक समान तरीके से काम करता है, सिवाय इसके कि नई कमांड चिल्ड्रेन इंस्टेंस में प्रचारित होगी। आपको this ऑब्जेक्ट का उपयोग करते समय सावधान रहना होगा क्योंकि मल्टीरिमोट browser और उसके चिल्ड्रेन इंस्टेंस के अलग-अलग this होते हैं।

यह उदाहरण दिखाता है कि मल्टीरिमोट के लिए एक नई कमांड कैसे जोड़ें।

import { multiremotebrowser } from '@wdio/globals'

multiremotebrowser.addCommand('getUrlAndTitle', async function (this: WebdriverIO.MultiRemoteBrowser, customVar: any) {
// `this` refers to:
// - MultiRemoteBrowser scope for browser
// - Browser scope for instances
return {
url: await this.getUrl(),
title: await this.getTitle(),
customVar: customVar
}
})

multiremotebrowser.getUrlAndTitle()
/*
{
url: [ 'https://webdriver.io/', 'https://webdriver.io/' ],
title: [
'WebdriverIO · Next-gen browser and mobile automation test framework for Node.js | WebdriverIO',
'WebdriverIO · Next-gen browser and mobile automation test framework for Node.js | WebdriverIO'
],
customVar: undefined
}
*/

multiremotebrowser.getInstance('browserA').getUrlAndTitle()
/*
{
url: 'https://webdriver.io/',
title: 'WebdriverIO · Next-gen browser and mobile automation test framework for Node.js | WebdriverIO',
customVar: undefined
}
*/

टाइप डेफिनिशन्स का विस्तार

TypeScript के साथ, WebdriverIO इंटरफेस का विस्तार करना आसान है। अपने कस्टम कमांड्स के लिए टाइप इस प्रकार जोड़ें:

  1. एक टाइप डेफिनिशन फाइल बनाएं (जैसे, ./src/types/wdio.d.ts)

  2. a. यदि मॉड्यूल-स्टाइल टाइप डेफिनिशन फाइल का उपयोग कर रहे हैं (टाइप डेफिनिशन फाइल में import/export और declare global WebdriverIO का उपयोग करके), सुनिश्चित करें कि फ़ाइल पथ को tsconfig.json include प्रॉपर्टी में शामिल किया गया है।

    b. यदि ambient-style टाइप डेफिनिशन फाइल्स का उपयोग कर रहे हैं (टाइप डेफिनिशन फाइल्स में कोई import/export नहीं और कस्टम कमांड्स के लिए declare namespace WebdriverIO), सुनिश्चित करें कि tsconfig.json में कोई include सेक्शन नहीं है, क्योंकि इससे include सेक्शन में सूचीबद्ध नहीं की गई सभी टाइप डेफिनिशन फाइल्स को टाइपस्क्रिप्ट द्वारा पहचाना नहीं जाएगा।

tsconfig.json
{
"compilerOptions": { ... },
"include": [
"./test/**/*.ts",
"./src/types/**/*.ts"
]
}
  1. अपने एक्जीक्यूशन मोड के अनुसार अपने कमांड्स के लिए डेफिनिशन्स जोड़ें।
declare global {
namespace WebdriverIO {
interface Browser {
browserCustomCommand: (arg: any) => Promise<void>
}

interface MultiRemoteBrowser {
browserCustomCommand: (arg: any) => Promise<void>
}

interface Element {
elementCustomCommand: (arg: any) => Promise<number>
}
}
}

तृतीय पक्ष लाइब्रेरी का एकीकरण

यदि आप बाहरी लाइब्रेरी का उपयोग करते हैं (जैसे, डेटाबेस कॉल करने के लिए) जो प्रॉमिस का समर्थन करती हैं, तो उन्हें एकीकृत करने का एक अच्छा तरीका है कि कुछ API मेथड्स को कस्टम कमांड के साथ रैप करें।

प्रॉमिस लौटाते समय, WebdriverIO यह सुनिश्चित करता है कि जब तक प्रॉमिस हल नहीं हो जाता, तब तक अगली कमांड के साथ आगे नहीं बढ़ा जाए। यदि प्रॉमिस अस्वीकृत हो जाता है, तो कमांड एक त्रुटि फेंकेगी।

browser.addCommand('makeRequest', async (url) => {
const response = await fetch(url)
return await response.json()
})

फिर, इसे अपने WDIO टेस्ट स्पेक्स में उपयोग करें:

it('execute external library in a sync way', async () => {
await browser.url('...')
const body = await browser.makeRequest('http://...')
console.log(body) // returns response body
})

नोट: आपकी कस्टम कमांड का परिणाम आपके द्वारा लौटाए गए प्रॉमिस का परिणाम है।

कमांड्स को ओवरराइट करना

आप overwriteCommand के साथ नेटिव कमांड्स को भी ओवरराइट कर सकते हैं।

ऐसा करने की सिफारिश नहीं की जाती है, क्योंकि इससे फ्रेमवर्क के अप्रत्याशित व्यवहार की ओर ले जा सकता है!

समग्र दृष्टिकोण addCommand के समान है, एकमात्र अंतर यह है कि कमांड फंक्शन में पहला आर्गुमेंट मूल फंक्शन है जिसे आप ओवरराइट करने जा रहे हैं। कृपया नीचे कुछ उदाहरण देखें।

ब्राउज़र कमांड्स को ओवरराइट करना

/**
* print milliseconds before pause and return its value.
*/
// 'pause' - name of command to be overwritten
// origPauseFunction - original pause function
browser.overwriteCommand('pause', async (origPauseFunction, ms) => {
console.log(`sleeping for ${ms}`)
await origPauseFunction(ms)
return ms
})

// then use it as before
console.log(`was sleeping for ${await browser.pause(1000)}`)

एलिमेंट कमांड्स को ओवरराइट करना

एलिमेंट स्तर पर कमांड्स को ओवरराइट करना लगभग एक जैसा है। बस overwriteCommand में तीसरे आर्गुमेंट के रूप में true पास करें:

/**
* Attempt to scroll to element if it is not clickable.
* Pass { force: true } to click with JS even if element is not visible or clickable.
*/
// 'click' - name of command to be overwritten
// origClickFunction - original click function
browser.overwriteCommand('click', async function (origClickFunction, { force = false } = {}) {
if (!force) {
try {
// attempt to click
await origClickFunction()
return null
} catch (err) {
if (err.message.includes('not clickable at point')) {
console.warn('WARN: Element', this.selector, 'is not clickable.',
'Scrolling to it before clicking again.')

// scroll to element and click again
await this.scrollIntoView()
return origClickFunction()
}
throw err
}
}

// clicking with js
console.warn('WARN: Using force click for', this.selector)
await browser.execute((el) => {
el.click()
}, this)
}, true) // don't forget to pass `true` as 3rd argument

// then use it as before
const elem = await $('body')
await elem.click()

// or pass params
await elem.click({ force: true })

अधिक WebDriver कमांड्स जोड़ें

यदि आप WebDriver प्रोटोकॉल का उपयोग कर रहे हैं और एक ऐसे प्लेटफॉर्म पर टेस्ट चला रहे हैं जो @wdio/protocols में परिभाषित किसी भी प्रोटोकॉल परिभाषा द्वारा परिभाषित नहीं किए गए अतिरिक्त कमांड्स का समर्थन करता है, तो आप उन्हें मैन्युअल रूप से addCommand इंटरफेस के माध्यम से जोड़ सकते हैं। webdriver पैकेज एक कमांड रैपर प्रदान करता है जो इन नए एंडपॉइंट्स को अन्य कमांड्स के समान तरीके से रजिस्टर करने की अनुमति देता है, जिससे वही पैरामीटर चेक और त्रुटि प्रबंधन प्रदान करता है। इस नए एंडपॉइंट को रजिस्टर करने के लिए कमांड रैपर को इम्पोर्ट करें और इसके साथ एक नई कमांड को रजिस्टर करें:

import { command } from 'webdriver'

browser.addCommand('myNewCommand', command('POST', '/session/:sessionId/foobar/:someId', {
command: 'myNewCommand',
description: 'a new WebDriver command',
ref: 'https://vendor.com/commands/#myNewCommand',
variables: [{
name: 'someId',
description: 'some id to something'
}],
parameters: [{
name: 'foo',
type: 'string',
description: 'a valid parameter',
required: true
}]
}))

इस कमांड को अवैध पैरामीटर्स के साथ कॉल करने से वही त्रुटि प्रबंधन होता है जो पूर्वनिर्धारित प्रोटोकॉल कमांड्स के लिए होता है, उदाहरण के लिए:

// call command without required url parameter and payload
await browser.myNewCommand()

/**
* results in the following error:
* Error: Wrong parameters applied for myNewCommand
* Usage: myNewCommand(someId, foo)
*
* Property Description:
* "someId" (string): some id to something
* "foo" (string): a valid parameter
*
* For more info see https://my-api.com
* at Browser.protocolCommand (...)
* ...
*/

कमांड को सही तरीके से कॉल करने पर, जैसे browser.myNewCommand('foo', 'bar'), सही ढंग से http://localhost:4444/session/7bae3c4c55c3bf82f54894ddc83c5f31/foobar/foo जैसे URL पर एक WebDriver अनुरोध भेजता है, जिसका पेलोड { foo: 'bar' } जैसा होता है।

नोट

:sessionId url पैरामीटर स्वचालित रूप से WebDriver सत्र के सत्र आईडी से बदल दिया जाएगा। अन्य url पैरामीटर लागू किए जा सकते हैं लेकिन उन्हें variables के भीतर परिभाषित किया जाना चाहिए।

देखें कि प्रोटोकॉल कमांड्स को कैसे परिभाषित किया जा सकता है इसके उदाहरण @wdio/protocols पैकेज में हैं।

Welcome! How can I help?

WebdriverIO AI Copilot