Skip to content

Commit

Permalink
Merge 37907da into 5bc9364
Browse files Browse the repository at this point in the history
  • Loading branch information
ph-fritsche authored Jan 31, 2021
2 parents 5bc9364 + 37907da commit 79f8284
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 0 deletions.
86 changes: 86 additions & 0 deletions src/__tests__/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import {
getWindowFromNode,
checkContainerType,
runWithRealTimers,
isInstanceOfElement,
} from '../helpers'
import {render} from './helpers/test-utils'

const globalObj = typeof window === 'undefined' ? global : window

Expand Down Expand Up @@ -53,6 +55,90 @@ describe('query container validation throws when validation fails', () => {
})
})

describe('check element type per isInstanceOfElement', () => {
let defaultViewDescriptor, spanDescriptor
beforeAll(() => {
defaultViewDescriptor = Object.getOwnPropertyDescriptor(
Object.getPrototypeOf(global.document),
'defaultView',
)
spanDescriptor = Object.getOwnPropertyDescriptor(
global.window,
'HTMLSpanElement',
)
})
afterEach(() => {
Object.defineProperty(
Object.getPrototypeOf(global.document),
'defaultView',
defaultViewDescriptor,
)
Object.defineProperty(global.window, 'HTMLSpanElement', spanDescriptor)
})

test('check in regular jest environment', () => {
const {container} = render(`<span></span>`)

expect(container.firstChild.ownerDocument.defaultView).toEqual(
expect.objectContaining({
HTMLSpanElement: expect.any(Function),
}),
)

expect(isInstanceOfElement(container.firstChild, 'HTMLSpanElement')).toBe(
true,
)
expect(isInstanceOfElement(container.firstChild, 'HTMLDivElement')).toBe(
false,
)
})

test('check in detached document', () => {
const {container} = render(`<span></span>`)

Object.defineProperty(
Object.getPrototypeOf(container.ownerDocument),
'defaultView',
{value: null},
)

expect(container.firstChild.ownerDocument.defaultView).toBe(null)

expect(isInstanceOfElement(container.firstChild, 'HTMLSpanElement')).toBe(
true,
)
expect(isInstanceOfElement(container.firstChild, 'HTMLDivElement')).toBe(
false,
)
})

test('check in environment not providing constructors on window', () => {
const {container} = render(`<span></span>`)

delete global.window.HTMLSpanElement

expect(container.firstChild.ownerDocument.defaultView.HTMLSpanElement).toBe(
undefined,
)

expect(isInstanceOfElement(container.firstChild, 'HTMLSpanElement')).toBe(
true,
)
expect(isInstanceOfElement(container.firstChild, 'HTMLDivElement')).toBe(
false,
)
})

test('throw error if element is not created by HTML*Element constructor', () => {
const doc = new Document()

// constructor is global.Element
const element = doc.createElement('span')

expect(() => isInstanceOfElement(element, 'HTMLSpanElement')).toThrow()
})
})

test('should always use realTimers before using callback when timers are faked with useFakeTimers', () => {
const originalSetTimeout = globalObj.setTimeout

Expand Down
31 changes: 31 additions & 0 deletions src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,36 @@ function getWindowFromNode(node) {
}
}

/**
* Check if an element is of a given type.
*
* @param Element The element to test
* @param string Constructor name. E.g. 'HTMLSelectElement'
*/
function isInstanceOfElement(element, elementType) {
try {
const window = getWindowFromNode(element)
// Window usually has the element constructors as properties but is not required to do so per specs
if (typeof window[elementType] === 'function') {
return element instanceof window[elementType]
}
} catch (e) {
// The document might not be associated with a window
}

// Fall back to the constructor name as workaround for test environments that
// a) not associate the document with a window
// b) not provide the constructor as property of window
if (/^HTML(\w+)Element$/.test(element.constructor.name)) {
return element.constructor.name === elementType
}

// The user passed some node that is not created in a browser-like environment
throw new Error(
`Unable to verify if element is instance of ${elementType}. Please file an issue describing your test environment: https://github.com/testing-library/dom-testing-library/issues/new`,
)
}

function checkContainerType(container) {
if (
!container ||
Expand Down Expand Up @@ -131,4 +161,5 @@ export {
checkContainerType,
jestFakeTimersAreEnabled,
TEXT_NODE,
isInstanceOfElement,
}

0 comments on commit 79f8284

Please sign in to comment.