Skip to content

Instantly share code, notes, and snippets.

@rhythnic
Last active December 17, 2018 21:52
Show Gist options
  • Save rhythnic/fb6d4f0f5ec0d9c1266e827f145a62f6 to your computer and use it in GitHub Desktop.
Save rhythnic/fb6d4f0f5ec0d9c1266e827f145a62f6 to your computer and use it in GitHub Desktop.
Helpers for composing Selenium tests into functional pipelines.
// Usage with Jest
//
// const loginForm = [
// {
// selector: '#login_username',
// property: 'username'
// },
// {
// selector: '#login_password',
// property: 'password'
// }
// ]
// const user = {
// username: 'admin',
// password: 'password'
// }
//
// test('User can login', () => seq(
// ctx => ctx.driver.get(LOGIN_URL).then(() => {}),
// fillForm(loginForm, user),
// click('button[type="submit"]')
// )({ driver, timeout: 2000 }))
const { until, By } = require('selenium-webdriver')
const { curry, merge } = require('ramda')
function normalizeArg (x, ctx) {
return typeof x === 'function' ? x(ctx) : x
}
function normalizeSelector (x, ctx) {
return typeof x === 'string' ? By.css(x) : x
}
const seq = (...fns) => async function seq (ctx) {
for (let i = 0; i < fns.length; i++) {
ctx = merge(ctx, await fns[i](ctx))
}
return ctx
}
const tap = fn => async ctx => {
await fn(ctx)
return null
}
const sleep = ms => async ctx => {
await ctx.driver.sleep(ms)
return null
}
const getElement = curry(async function getElement (selector, ctx) {
selector = normalizeArg(selector, ctx)
const element = await ctx.driver.wait(
until.elementLocated(normalizeSelector(selector)),
ctx.timeout
)
await ctx.driver.wait(until.elementIsVisible(element), ctx.timeout)
return { selector, element }
})
const click = selector => async function click (ctx) {
if (selector) {
ctx = await getElement(selector, ctx)
}
await ctx.element.click()
return ctx
}
const getText = (selector, prop = 'text') => async function getText (ctx) {
if (selector) {
ctx = await getElement(selector, ctx)
}
ctx[prop] = await ctx.element.getText()
return ctx
}
const sendKeys = (selector, text) => async function sendKeys (ctx) {
text = normalizeArg(text, ctx)
if (selector) {
ctx = await getElement(selector, ctx)
}
await ctx.element.sendKeys(text)
return ctx
}
const fillForm = curry(async function fillForm (fields, data, ctx) {
for (let i = 0; i < fields.length; i++) {
let { selector, property, type } = fields[i]
if (selector.includes('{{value}}')) {
selector = selector.replace('{{value}}', data[property])
}
let { element } = await getElement(selector, ctx)
switch ((type || '').toLowerCase()) {
case 'select':
await element.click()
break
default:
await element.sendKeys(data[property])
}
}
return
})
module.exports = {
seq,
tap,
sleep,
getElement,
getText,
sendKeys,
click,
fillForm
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment