import { browser, expect, $ } from '@wdio/globals'
import { spyOn, mock, fn, unmock } from '@wdio/browser-runner'
import { html, render } from 'lit'
import isUrl from 'is-url'
import defaultExport, { namedExportValue } from 'someModule'
import namespacedModule from '@namespace/module'
import { someExport, namedExports, someFunction } from '@testing-library/user-event'
/**
* a CJS module
*/
import stringWidth from 'string-width'
import { SimpleGreeting } from './components/LitComponent.ts'
const getQuestionFn = spyOn(SimpleGreeting.prototype, 'getQuestion')
mock('./components/constants.ts', async (mod) => {
return {
GREETING: mod.GREETING + ' Sir'
}
})
mock('string-width', () => ({
default: () => 123
}))
mock('graphql-request', () => ({
gql: fn(),
GraphQLClient: class GraphQLClientMock {
request = fn().mockResolvedValue({ result: 'Thanks for your answer!' })
}
}))
mock('@testing-library/user-event', async (mod) => {
return {
someExport: 'foobarloo',
namedExports: Object.keys(mod),
someFunction: fn()
.mockReturnValueOnce('first')
.mockReturnValueOnce('second')
.mockReturnValueOnce('third')
}
})
unmock('is-url')
mock('@namespace/module')
describe('Lit Component testing', () => {
it('recognises require files', () => {
expect(window.globalSetupScriptExecuted).toBe(true)
expect(window.mochaGlobalSetupExecuted).toBe(true)
})
it('should render component', async function () {
/**
* only run snapshot tests in non-Safari browsers as shadow dom piercing
* is not yet supported in Safari
*/
if (browser.capabilities.browserName?.toLowerCase() === 'safari') {
return
}
render(
html` Hello Sir, WebdriverIO! Does this work? I am within another shadow root element I am within another shadow root element as wellClosed Node
Deep Closed Node
Hello World
' const shadowExists = document.querySelector('#helloshadow')?.shadowRoot return shadowExists ? 'created' : 'failed' }) expect(shadowResult).toBe('created') const shadowRoot = await browser.execute(() => Boolean(document.querySelector('#helloshadow')?.shadowRoot) ) expect(shadowRoot).toBe(true) const shadowElement = await browser.execute(() => Boolean(document.querySelector('#helloshadow')?.shadowRoot?.querySelector('#shadowelement')) ) expect(shadowElement).toBe(true) await browser.$('#helloshadow').waitForDisplayed() await browser.$('#shadowelement').waitForExist() }) }) it('maps the driver response when the element is not interactable so that we shown an aligned message with the best information we can', async () => { render( html``, document.body ) const err = await $('input').click().catch((err) => err) expect(err.name).toBe('webdriverio(middleware): element did not become interactable') expect(err.message).toBe('Element did not become interactable') }) it('intercepts "element not interactable" errors and waits for the element to be interactable', async () => { render( html``, document.body ) setTimeout(() => { document.querySelector('input').setAttribute('style', '') }, 1000) await $('input').click() }) it('intercepts "element not interactable" errors and waits for the element in array to be interactable', async () => { render( html``, document.body ) setTimeout(() => { document.querySelector('input').setAttribute('style', '') }, 1000) await $$('input')[0].click() }) it('should allow to auto mock dependencies', () => { expect(defaultExport).toBe('barfoo') expect(namedExportValue).toBe('foobar') expect(namespacedModule).toBe('some value') }) it('should allow to manual mock namespaces deps', async () => { expect(someExport).toBe('foobarloo') expect(namedExports).toEqual(['PointerEventsCheckLevel', 'default', 'userEvent']) }) it('should allow to have different mock return values', () => { expect(someFunction()).toBe('first') expect(someFunction()).toBe('second') expect(someFunction()).toBe('third') expect(someFunction()).toBe(undefined) }) it('should allow to mock CJS modules', () => { expect(stringWidth('a')).toBe(123) }) it('should allow to unmock', () => { expect(isUrl).not.toBe('mocked value') }) it('should have access to globals', () => { expect(process.env.WDIO_PRESET).toBe('lit') expect(window.WDIO_ENV_TEST).toBe('passed') expect(window.TEST_COMMAND).toBe('serve') }) it('should allow to manual mock dependencies', async function () { /** * this fails in Safari as the click on the button is not recognised */ if (browser.capabilities.browserName.toLowerCase() === 'safari') { return this.skip() } render( html`
`,
document.body
)
await expect($('aria/Find me')).toHaveAttribute('src', '/you/got/it.png')
})
it('aria label is received by an input placeholder', async () => {
// https://www.w3.org/TR/accname-1.1/#step2D
render(
html`
`,
document.body
)
await expect($$('aria/Find me')).toBeElementsArrayOfSize(2)
})
it('aria label is received by an input aria-placeholder', async () => {
// https://www.w3.org/TR/accname-1.1/#step2D
render(
html`
`,
document.body
)
await expect($$('aria/Find me')).toBeElementsArrayOfSize(2)
})
/**
* fails due to https://github.com/webdriverio/webdriverio/issues/8826
*/
it('input with a label', async () => {
// https://www.w3.org/TR/accname-1.1/#step2D
render(
html`
`,
document.body
)
const elem = await $('aria/Search')
await expect(elem).toHaveValue('Hello World!')
})
it('multiple inputs with a label', async () => {
// https://www.w3.org/TR/accname-1.1/#step2D
render(
html`
`,
document.body
)
const elem1 = await $('aria/Search 1')
await expect(elem1).toHaveValue('Hello World! 1')
const elem2 = await $('aria/Search 2')
await expect(elem2).toHaveValue('Hello World 2')
})
it('textarea with a label', async () => {
// https://www.w3.org/TR/accname-1.1/#step2D
render(
html`
`,
document.body
)
const elem = await $('aria/Search')
await expect(elem).toHaveValue('Hello World!')
})
it('multiple textareas with a label', async () => {
// https://www.w3.org/TR/accname-1.1/#step2D
render(
html`
`,
document.body
)
const elem1 = await $('aria/Search 1')
await expect(elem1).toHaveValue('Hello World! 1')
const elem2 = await $('aria/Search 2')
await expect(elem2).toHaveValue('Hello World 2')
})
it('input with a label as parent', async () => {
// https://www.w3.org/TR/accname-1.1/#step2D
render(
html`
`,
document.body
)
const elem = await $('aria/Search')
await expect(elem).toHaveValue('Hello World!')
})
it('multiple inputs with a label as parent', async () => {
// https://www.w3.org/TR/accname-1.1/#step2D
render(
html`
`,
document.body
)
const elem1 = await $('aria/Search 1')
await expect(elem1).toHaveValue('Hello World! 1')
const elem2 = await $('aria/Search 2')
await expect(elem2).toHaveValue('Hello World! 2')
})
it('textarea with a label as parent', async () => {
// https://www.w3.org/TR/accname-1.1/#step2D
render(
html`
`,
document.body
)
const elem = await $('aria/Search')
await expect(elem).toHaveValue('Hello World!')
})
it('multiple textareas with a label as parent', async () => {
// https://www.w3.org/TR/accname-1.1/#step2D
render(
html`
`,
document.body
)
const elem1 = await $('aria/Search 1')
await expect(elem1).toHaveValue('Hello World! 1')
const elem2 = await $('aria/Search 2')
await expect(elem2).toHaveValue('Hello World! 2')
})
it('aria label is recevied by other element with aria-labelledBy', async () => {
// https://www.w3.org/TR/accname-1.1/#step2B
render(
html`