Skip to content

Commit

Permalink
Make it easier to add commands that make WebDriver based requests (we…
Browse files Browse the repository at this point in the history
  • Loading branch information
christian-bromann authored Mar 17, 2021
1 parent 2ed0700 commit 5418211
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 39 deletions.
1 change: 1 addition & 0 deletions .husky/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_
3 changes: 3 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

git diff-index --name-only --diff-filter=d HEAD | grep -E "(.*)\\.js$" | xargs node_modules/eslint/bin/eslint.js -c .eslintrc.js
3 changes: 3 additions & 0 deletions .husky/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

npm run test:eslint
52 changes: 26 additions & 26 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 2 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
"ts:sync": "cd tests/typings/sync && npx tsc",
"watch": "node ./scripts/build --watch",
"watch:docs": "npm run docs:generate && cd website && npm i && npm start",
"version": "npm run changelog && git add CHANGELOG.md"
"version": "npm run changelog && git add CHANGELOG.md",
"postinstall": "husky install"
},
"devDependencies": {
"@cucumber/cucumber": "^7.0.0",
Expand Down Expand Up @@ -99,11 +100,5 @@
"typescript": "4.0.5",
"url-join": "^4.0.1"
},
"husky": {
"hooks": {
"pre-commit": "git diff-index --name-only --diff-filter=d HEAD | grep -E \"(.*)\\.js$\" | xargs node_modules/eslint/bin/eslint.js -c .eslintrc.js",
"pre-push": "npm run test:eslint"
}
},
"dependencies": {}
}
4 changes: 2 additions & 2 deletions packages/webdriver/src/command.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logger from '@wdio/logger'
import { commandCallStructure, isValidParameter, getArgumentType } from '@wdio/utils'
import Protocols from '@wdio/protocols'
import type { CommandEndpoint } from '@wdio/protocols'

import WebDriverRequest, { WebDriverResponse } from './request'
import { BaseClient } from './types'
Expand All @@ -10,7 +10,7 @@ const log = logger('webdriver')
export default function (
method: string,
endpointUri: string,
commandInfo: Protocols.CommandEndpoint,
commandInfo: CommandEndpoint,
doubleEncodeVariables = false
) {
const { command, ref, parameters, variables = [], isHubCommand = false } = commandInfo
Expand Down
3 changes: 2 additions & 1 deletion packages/webdriver/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { webdriverMonad, sessionEnvironmentDetector } from '@wdio/utils'
import { validateConfig } from '@wdio/config'
import type { Options, Capabilities } from '@wdio/types'

import command from './command'
import { DEFAULTS } from './constants'
import { startWebDriverSession, getPrototype, getEnvironmentVars } from './utils'
import type { Client, AttachOptions, SessionFlags } from './types'
Expand Down Expand Up @@ -119,5 +120,5 @@ export default class WebDriver {
/**
* Helper methods consumed by webdriverio package
*/
export { getPrototype, DEFAULTS }
export { getPrototype, DEFAULTS, command }
export * from './types'
4 changes: 3 additions & 1 deletion packages/webdriver/tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import logger, { logMock } from '@wdio/logger'
import * as wdioUtils from '@wdio/utils'
import { Capabilities } from '@wdio/types'

import WebDriver, { getPrototype, DEFAULTS } from '../src'
import WebDriver, { getPrototype, DEFAULTS, command } from '../src'
import { Client } from '../src/types'

const expect = global.expect as unknown as jest.Expect
Expand Down Expand Up @@ -58,7 +58,9 @@ describe('WebDriver', () => {
test('exports getPrototype, DEFAULTS', () => {
expect(typeof getPrototype).toBe('function')
expect(typeof DEFAULTS).toBe('object')
expect(typeof command).toBe('function')
})

describe('newSession', () => {
afterEach(() => {
delete process.env.WDIO_LOG_PATH
Expand Down
57 changes: 55 additions & 2 deletions website/docs/CustomCommands.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ it('execute external library in a sync way', () => {

**Note:** The result of your custom command is the result of the promise you return. Also, there is no support for synchronous commands in standalone mode; therefore, you must _always_ handle asynchronous commands using promises.

### Overwriting native commands
## Overwriting native commands

You can also overwrite native commands with `overwriteCommand`.

Expand All @@ -124,7 +124,7 @@ The overall approach is similar to `addCommand`, the only difference is that the

**NOTE:** Examples below assume sync mode. If you are not using it, don't forget to add `async`/`await`.

#### Overwriting browser commands
### Overwriting browser commands

```js
/**
Expand Down Expand Up @@ -185,3 +185,56 @@ elem.click()
// or pass params
elem.click({ force: true })
```

## Add More WebDriver Commands

If you are using the WebDriver protocol and run tests on a platform that supports additional commands not defined by any of the protocol definitions in [`@wdio/protocols`](https://github.com/webdriverio/webdriverio/tree/main/packages/wdio-protocols/protocols) you can manually add them through the `addCommand` interface. The `webdriver` package offers a command wrapper that allows to register these new endpoints in the same way as other commands, providing the same parameter checks and error handling. To register this new endpoint import the command wrapper and register a new command with it as follows:

```js
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
}]
}))
```

Calling this command with invalid parameters results in the same error handling as predefined protocol commands, e.g.:

```js
// call command without required url parameter and payload
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 (...)
* ...
*/
```

Calling the command correctly, e.g. `browser.myNewCommand('foo', 'bar')`, correctly makes a WebDriver request to e.g. `http://localhost:4444/session/7bae3c4c55c3bf82f54894ddc83c5f31/foobar/foo` with a payload like `{ foo: 'bar' }`.

:::note
The `:sessionId` url parameter will be automatically substituted with the session id of the WebDriver session. Other url parameter can be applied but need to be defined within `variables`.
:::

See examples of how protocol commands can be defined in the [`@wdio/protocols`](https://github.com/webdriverio/webdriverio/tree/main/packages/wdio-protocols/protocols) package.

0 comments on commit 5418211

Please sign in to comment.