Skip to content

Commit

Permalink
feat(logDOM): add logDOM export
Browse files Browse the repository at this point in the history
  • Loading branch information
Kent C. Dodds committed Aug 9, 2019
1 parent 6b504ad commit 1d2d56b
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 67 deletions.
66 changes: 50 additions & 16 deletions src/__tests__/pretty-dom.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,61 @@
import {prettyDOM} from '../pretty-dom'
import {render} from './helpers/test-utils'
import {prettyDOM, logDOM} from '../pretty-dom'
import {render, renderIntoDocument} from './helpers/test-utils'

test('prints out the given DOM element tree', () => {
beforeEach(() => {
jest.spyOn(console, 'log').mockImplementation(() => {})
})

afterEach(() => {
console.log.mockRestore()
})

test('prettyDOM prints out the given DOM element tree', () => {
const {container} = render('<div>Hello World!</div>')
expect(prettyDOM(container)).toMatchInlineSnapshot(`
"<div>
<div>
Hello World!
</div>
</div>"
`)
"<div>
<div>
Hello World!
</div>
</div>"
`)
})

test('supports truncating the output length', () => {
test('prettyDOM supports truncating the output length', () => {
const {container} = render('<div>Hello World!</div>')
expect(prettyDOM(container, 5)).toMatch(/\.\.\./)
})

test('supports receiving the document element', () => {
test('prettyDOM defaults to document.body', () => {
renderIntoDocument('<div>Hello World!</div>')
expect(prettyDOM()).toMatchInlineSnapshot(`
"<body>
<div>
Hello World!
</div>
</body>"
`)
})

test('prettyDOM supports receiving the document element', () => {
expect(prettyDOM(document)).toMatchInlineSnapshot(`
"<html>
<head />
<body />
</html>"
`)
"<html>
<head />
<body />
</html>"
`)
})

test('logDOM logs prettyDOM to the console', () => {
const {container} = render('<div>Hello World!</div>')
logDOM(container)
expect(console.log).toHaveBeenCalledTimes(1)
expect(console.log.mock.calls[0][0]).toMatchInlineSnapshot(`
"<div>
<div>
Hello World!
</div>
</div>"
`)
})

/* eslint no-console:0 */
17 changes: 10 additions & 7 deletions src/__tests__/role-helpers.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import {getRoles, logRoles, getImplicitAriaRoles} from '../role-helpers'
import {render} from './helpers/test-utils'

beforeEach(() => {
jest.spyOn(console, 'log').mockImplementation(() => {})
})

afterEach(() => {
console.log.mockRestore()
})

function setup() {
const {getByTestId} = render(`
<section data-testid='a-section'>
Expand Down Expand Up @@ -137,16 +145,9 @@ test('getRoles returns expected roles for various dom nodes', () => {

test('logRoles calls console.log with output from prettyRoles', () => {
const {section} = setup()

jest.spyOn(console, 'log').mockImplementationOnce(() => {})

logRoles(section)
// eslint-disable-next-line no-console
expect(console.log).toHaveBeenCalledTimes(1)
// eslint-disable-next-line no-console
expect(console.log.mock.calls[0][0]).toMatchSnapshot()
// eslint-disable-next-line no-console
console.log.mockRestore()
})

test('getImplicitAriaRoles returns expected roles for various dom nodes', () => {
Expand All @@ -158,3 +159,5 @@ test('getImplicitAriaRoles returns expected roles for various dom nodes', () =>
expect(getImplicitAriaRoles(radio)).toEqual(['radio'])
expect(getImplicitAriaRoles(input)).toEqual(['textbox'])
})

/* eslint no-console:0 */
43 changes: 36 additions & 7 deletions src/pretty-dom.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,50 @@
import prettyFormat from 'pretty-format'
import {getDocument} from './helpers'

function inCypress(dom) {
const window =
(dom.ownerDocument && dom.ownerDocument.defaultView) || undefined
return (
(typeof global !== 'undefined' && global.Cypress) ||
(typeof window !== 'undefined' && window.Cypress)
)
}

const inNode = () =>
typeof process !== 'undefined' &&
process.versions !== undefined &&
process.versions.node !== undefined

const getMaxLength = dom =>
inCypress(dom) ? 0 : process.env.DEBUG_PRINT_LIMIT || 7000

const {DOMElement, DOMCollection} = prettyFormat.plugins

function prettyDOM(htmlElement, maxLength, options) {
if (htmlElement.documentElement) {
htmlElement = htmlElement.documentElement
function prettyDOM(
dom = getDocument().body,
maxLength = getMaxLength(dom),
options,
) {
if (maxLength === 0) {
return ''
}
if (dom.documentElement) {
dom = dom.documentElement
}

const debugContent = prettyFormat(htmlElement, {
const debugContent = prettyFormat(dom, {
plugins: [DOMElement, DOMCollection],
printFunctionName: false,
highlight: true,
highlight: inNode(),
...options,
})
return maxLength !== undefined && htmlElement.outerHTML.length > maxLength
return maxLength !== undefined && dom.outerHTML.length > maxLength
? `${debugContent.slice(0, maxLength)}...`
: debugContent
}

export {prettyDOM}
const logDOM = (...args) => console.log(prettyDOM(...args))

export {prettyDOM, logDOM}

/* eslint no-console:0 */
28 changes: 1 addition & 27 deletions src/query-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,8 @@ import {prettyDOM} from './pretty-dom'
import {fuzzyMatches, matches, makeNormalizer} from './matches'
import {waitForElement} from './wait-for-element'

/* eslint-disable complexity */
function debugDOM(htmlElement) {
const limit = process.env.DEBUG_PRINT_LIMIT || 7000
const inNode =
typeof process !== 'undefined' &&
process.versions !== undefined &&
process.versions.node !== undefined
/* istanbul ignore next */
const window =
(htmlElement.ownerDocument && htmlElement.ownerDocument.defaultView) ||
undefined
const inCypress =
(typeof global !== 'undefined' && global.Cypress) ||
(typeof window !== 'undefined' && window.Cypress)
/* istanbul ignore else */
if (inCypress) {
return ''
} else if (inNode) {
return prettyDOM(htmlElement, limit)
} else {
return prettyDOM(htmlElement, limit, {highlight: false})
}
}
/* eslint-enable complexity */

function getElementError(message, container) {
return new Error([message, debugDOM(container)].filter(Boolean).join('\n\n'))
return new Error([message, prettyDOM(container)].filter(Boolean).join('\n\n'))
}

function getMultipleElementsFoundError(message, container) {
Expand Down Expand Up @@ -111,7 +86,6 @@ function buildQueries(queryAllBy, getMultipleError, getMissingError) {
}

export {
debugDOM,
getElementError,
getMultipleElementsFoundError,
queryAllByAttribute,
Expand Down
15 changes: 7 additions & 8 deletions src/role-helpers.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {elementRoles} from 'aria-query'
import {debugDOM} from './query-helpers'
import {prettyDOM} from './pretty-dom'

const elementRoleList = buildElementRoleList(elementRoles)

Expand Down Expand Up @@ -73,24 +73,23 @@ function getRoles(container) {
}, {})
}

function prettyRoles(container) {
const roles = getRoles(container)
function prettyRoles(dom) {
const roles = getRoles(dom)

return Object.entries(roles)
.map(([role, elements]) => {
const delimiterBar = '-'.repeat(50)
const elementsString = elements
.map(el => debugDOM(el.cloneNode(false)))
.map(el => prettyDOM(el.cloneNode(false)))
.join('\n\n')

return `${role}:\n\n${elementsString}\n\n${delimiterBar}`
})
.join('\n')
}

function logRoles(container) {
// eslint-disable-next-line no-console
console.log(prettyRoles(container))
}
const logRoles = dom => console.log(prettyRoles(dom))

export {getRoles, logRoles, getImplicitAriaRoles, prettyRoles}

/* eslint no-console:0 */
4 changes: 2 additions & 2 deletions typings/query-helpers.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export type AllByAttribute = (

export const queryByAttribute: QueryByAttribute
export const queryAllByAttribute: AllByAttribute
export const debugDOM: (htmlElement: HTMLElement) => string
export const logDOM: (htmlElement: HTMLElement) => void
export const getElementError: (message: string, container: HTMLElement) => Error

/**
Expand Down Expand Up @@ -53,7 +53,7 @@ export type BuiltQueryMethods<Arguments extends any[]> = [
GetAllBy<Arguments>,
GetBy<Arguments>,
FindAllBy<Arguments>,
FindBy<Arguments>
FindBy<Arguments>,
]
export const buildQueries: <Arguments extends any[]>(
queryByAll: GetAllBy<Arguments>,
Expand Down

0 comments on commit 1d2d56b

Please sign in to comment.