import path from 'node:path'
import assert from 'node:assert'
describe('Mocha smoke test', () => {
const testJs = path.join('tests', 'mocha', 'test.ts')
it('has globals set up', async () => {
expect(1).toBe(1)
expect(global.browser).toBeDefined()
expect(global.driver).toBeDefined()
expect(global.$).toBeDefined()
expect(global.$$).toBeDefined()
expect(global.expect).toBeDefined()
})
it('should allow to use WebdriverIO assertions', async () => {
await expect(browser).toHaveTitle('Mock Page Title')
})
it('should allow to use asymmetric matchers', async () => {
await expect(browser).toHaveTitle(
expect.stringContaining('Page'))
await expect(browser).toHaveTitle(
expect.not.stringContaining('foobar'))
await expect(browser).toHaveUrl(
expect.stringContaining('mymockpage'))
await expect(browser).toHaveUrl(
expect.not.stringContaining('mymock_page.'))
})
it('has a testrunner config object', () => {
const opts = browser.options as WebdriverIO.Config
expect(Array.isArray(opts.services)).toBe(true)
expect(opts).toHaveProperty('mochaOpts')
expect(opts).toHaveProperty('jasmineOpts')
expect(opts).toHaveProperty('cucumberOpts')
expect(opts).toHaveProperty('specs')
})
let hasRun = false
it('should retry', function (this: WebdriverIO.Browser) {
if (!hasRun) {
hasRun = true
assert.equal(this.wdioRetries, 0)
throw new Error('booom!')
}
assert.equal(this.wdioRetries, 1)
}, 1)
it('should chain properly', async () => {
await browser.isExistingScenario()
const el = browser.$('body')
assert.equal(await el.$('.selector-1').isExisting(), true)
assert.equal(await el.$('.selector-2').isExisting(), true)
})
it('should allow to use then/catch/finally', async () => {
await browser.isExistingScenario()
const val = await browser.$('body').$('.selector-1').then(() => 123)
expect(val).toBe(123)
await browser.isExistingScenario()
let anotherVal
const elem = await browser.$('body').$('.selector-1').finally(() => {
anotherVal = 321
})
expect(elem.selector).toBe('.selector-1')
expect(anotherVal).toBe(321)
await browser.isNotExistingScenario()
const errorVal = await browser.$('body').$('.fooobar').catch(() => 42)
expect(errorVal).toBe(42)
})
it('should allow chaining of custom$', async () => {
browser.addLocatorStrategy('someSelector', () => global.document.body)
await browser.customSelectorScenario()
const el = await browser.$('body').custom$('someSelector', 'foo').$('div#foobar')
expect(el.selector).toBe('div#foobar')
})
it('should allow to chain custom commands', async () => {
await browser.isExistingScenario()
browser.addCommand(
'foo',
function (this: WebdriverIO.Element) {
return Promise.resolve('foo').then((r) => `${r}_${this.selector}_bar`)
},
true
)
expect(browser.foo).not.toBeDefined()
expect(await browser.$('body').$('.selector-1').foo()).toBe('foo_.selector-1_bar')
})
it('should allow to reload a session', async () => {
const sessionIdBefore = browser.sessionId
await browser.reloadSession()
expect(sessionIdBefore).not.toBe(browser.sessionId)
})
it('should handle promises in waitUntil callback funciton using async code', async () => {
const results: string[] = []
const result = await browser.waitUntil(async () => {
results.push(await browser.getUrl())
return results.length > 1
})
assert.strictEqual(result, true)
assert.deepEqual(results, ['https://mymockpage.com', 'https://mymockpage.com'])
})
it('should handle waitUntil timeout', async () => {
await browser.staleElementRefetchScenario()
const elem = await $('elem')
try {
await browser.waitUntil(async () => {
await elem.click()
return false
}, { timeout: 1000 })
} catch {
}
assert.equal(JSON.stringify(await elem.getSize()), JSON.stringify({ width: 1, height: 2 }))
})
describe('isDisplayed', () => {
it('should return false if element is never found', async () => {
await browser.isNeverDisplayedScenario()
const elem = await $('elem')
assert.equal(await elem.isDisplayed(), false)
})
it('should reFetch the element once', async () => {
await browser.isEventuallyDisplayedScenario()
const elem = await $('elem')
assert.equal(await elem.isDisplayed(), true)
})
})
describe('add customCommands', () => {
it('should allow to call nested custom commands', async () => {
browser.addCommand('myCustomCommand', async function (param) {
const result = {
url: await browser.getUrl(),
title: await browser.getTitle()
}
return { param, ...result }
})
assert.equal(
JSON.stringify(await browser.myCustomCommand('foobar')),
JSON.stringify({
param: 'foobar',
url: 'https://mymockpage.com',
title: 'Mock Page Title'
})
)
})
it('allows to create custom commands on elements', async () => {
await browser.customCommandScenario()
const elem = await $('elem')
elem.addCommand('myCustomCommand', async function (this: WebdriverIO.Element, param) {
const result = await this.getSize()
return { selector: this.selector, result, param }
})
assert.equal(
JSON.stringify(await elem.myCustomCommand('foobar')),
JSON.stringify({
selector: 'elem',
result: { width: 1, height: 2 },
param: 'foobar'
})
)
})
it('should keep the scope', async () => {
await browser.customCommandScenario()
browser.addCommand('customFn', async function (this: WebdriverIO.Element, elem: WebdriverIO.Element) {
return (await this.execute('1+1')) + '-' + elem.selector
})
assert.equal(await browser.customFn(await $('body')), '2-body')
})
it('should respect promises', async () => {
browser.addCommand('customFn', () => {
return Promise.resolve('foobar')
})
assert.equal(await browser.customFn(), 'foobar')
})
it('should throw if promise rejects', async () => {
browser.addCommand('customFn', () => {
return Promise.reject(new Error('Boom!'))
})
await assert.rejects(
async () => {
await browser.customFn()
},
error => {
const err = error as Error
assert.equal(err?.message, 'Boom!')
assert.equal(err?.stack?.includes(testJs), true)
return true
}
)
})
it('allows to create custom commands on elements that respects promises', async () => {
await browser.customCommandScenario()
browser.addCommand('myCustomPromiseCommand', function () {
return Promise.resolve('foobar')
}, true)
const elem = await $('elem')
assert.equal(await elem.myCustomPromiseCommand(), 'foobar')
})
})
describe('overwrite native commands', () => {
it('should allow to overwrite browser commands', async () => {
await browser.customCommandScenario()
browser.overwriteCommand('getTitle' as any, async function (origCommand, pre = '') {
return pre + await origCommand()
})
assert.equal(await browser.getTitle('Foo '), 'Foo Mock Page Title')
})
it('should allow to overwrite element commands', async () => {
await browser.customCommandScenario()
browser.overwriteCommand('getSize', (async (origCommand: Function, ratio = 1) => {
const { width, height } = await origCommand()
return { width: width * ratio, height: height * ratio }
}) as any, true)
const elem = await $('elem')
assert.equal(
JSON.stringify(await elem.getSize(2)),
JSON.stringify({ width: 2, height: 4 })
)
})
it('should allow to invoke native command on different element', async () => {
await browser.customCommandScenario()
browser.overwriteCommand('getSize', (async function (origCommand: Function, ratio = 1) {
const elemAlt = await $('elemAlt')
const { width, height } = await origCommand.call(elemAlt)
return { width: width * ratio, height: height * ratio }
}) as any, true)
const elem = await $('elem')
assert.equal(
JSON.stringify(await elem.getSize(2)),
JSON.stringify({ width: 20, height: 40 })
)
})
it('should keep the scope', async () => {
await browser.customCommandScenario()
browser.overwriteCommand('saveRecordingScreen', (async function (
this: WebdriverIO.Browser,
origCommand: Function,
filepath: string,
elem: WebdriverIO.Element
) {
if (elem) {
return (await this.execute('1+1')) + '-' + elem.selector
}
return origCommand(filepath)
}) as any)
assert.equal(await browser.saveRecordingScreen(null, await $('body')), '2-body')
})
it('should respect promises - browser', async () => {
await browser.customCommandScenario()
browser.overwriteCommand('getUrl' as any, async function (origCommand, append = '') {
return Promise.resolve((await origCommand()) + append)
})
assert.equal(await browser.getUrl('/foobar'), 'https://mymockpage.com/foobar')
})
it('should respect promises - element', async () => {
await browser.customCommandScenario()
browser.overwriteCommand('getHTML', async function (origCommand) {
return Promise.resolve(await origCommand())
}, true)
const elem = await $('elem')
assert.equal(await elem.getHTML(), '2')
})
it('should throw if promise rejects', async () => {
await browser.customCommandScenario()
browser.overwriteCommand('deleteCookies', (async (origCommand: Function) => {
await origCommand()
return Promise.reject(new Error('deleteAllCookies'))
}) as any)
await assert.rejects(
async () => {
await browser.deleteCookies(true)
},
error => {
const err = error as Error
assert.equal(err?.message, 'deleteAllCookies')
assert.equal(err?.stack?.includes(testJs), true)
return true
}
)
})
it('should throw if promise rejects (async execution)', async () => {
await browser.customCommandScenario()
browser.overwriteCommand('deleteCookies', async (origCommand: Function) => {
await origCommand()
return Promise.reject(new Error('deleteAllCookies'))
})
await assert.rejects(
async () => {
await browser.deleteCookies(true)
},
error => {
const err = error as Error
assert.equal(err?.message, 'deleteAllCookies')
assert.equal(err?.stack?.includes(testJs), true)
return true
}
)
})
})
describe('supports async iteration', () => {
beforeEach(async () => {
await browser.asyncIterationScenario()
})
it('by chaining commands', async () => {
expect(await $$('elem').map((el) => el.getText())).toEqual(
['some element text', 'some other element text'])
})
it('by defining vars first', async () => {
const elements = await $$('elem')
expect(await elements.map((el) => el.getText())).toEqual(
['some element text', 'some other element text'])
})
})
describe('supports refetching elements', () => {
it('should refetch elements', async () => {
await browser.refetchElementScenario()
expect(await browser.$$('.foo')[3].getText()).toBe('some element text 4')
})
})
describe('request retries', () => {
it('should retry request', async () => {
await browser.requestRetryScenario()
await browser.url('https://mymockpage.com')
})
})
describe('waitForExist', () => {
it('should return true if element exists', async () => {
await browser.waitForExistScenario()
const elem = await $('elem')
expect(elem.error).toBeDefined()
expect(elem.elementId).toBeUndefined()
expect(await elem.waitForExist()).toBe(true)
expect(elem.error).toBeUndefined()
expect(elem.elementId).toBeDefined()
})
})
it('supports inline snapshots', () => {
expect({ deep: { foo: 'bar' } }).toMatchInlineSnapshot(`
{
"deep": {
"foo": "bar",
},
}
`)
})
})