From 140bee7f42b4bd372c5f7535d70b9eb55d84aef5 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 12 Jul 2019 11:47:52 -0600 Subject: [PATCH] feat: log available roles when a roles query fails Closes #286 --- src/__tests__/element-queries.js | 6 +++--- src/__tests__/pretty-dom.js | 9 +++------ src/__tests__/role.js | 22 ++++++++++++++++++++++ src/queries/role.js | 16 +++++++++++++--- src/role-helpers.js | 10 ++++++---- 5 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 src/__tests__/role.js diff --git a/src/__tests__/element-queries.js b/src/__tests__/element-queries.js index db7e24e8..c01c0763 100644 --- a/src/__tests__/element-queries.js +++ b/src/__tests__/element-queries.js @@ -1,8 +1,6 @@ -import jestSerializerAnsi from 'jest-serializer-ansi' import {configure} from '../config' import {render, renderIntoDocument} from './helpers/test-utils' -expect.addSnapshotSerializer(jestSerializerAnsi) beforeEach(() => { document.defaultView.Cypress = null }) @@ -88,7 +86,9 @@ test('get throws a useful error message', () => { " `) expect(() => getByRole('LucyRicardo')).toThrowErrorMatchingInlineSnapshot(` -"Unable to find an element by [role=LucyRicardo] +"Unable to find an element with the role "LucyRicardo" + +Here are the available roles:
diff --git a/src/__tests__/pretty-dom.js b/src/__tests__/pretty-dom.js index 5acf6cf3..45e07c3d 100644 --- a/src/__tests__/pretty-dom.js +++ b/src/__tests__/pretty-dom.js @@ -1,10 +1,7 @@ -import jestSerializerAnsi from 'jest-serializer-ansi' import {prettyDOM} from '../pretty-dom' import {render} from './helpers/test-utils' -expect.addSnapshotSerializer(jestSerializerAnsi) - -test('it prints out the given DOM element tree', () => { +test('prints out the given DOM element tree', () => { const {container} = render('
Hello World!
') expect(prettyDOM(container)).toMatchInlineSnapshot(` "
@@ -15,12 +12,12 @@ test('it prints out the given DOM element tree', () => { `) }) -test('it supports truncating the output length', () => { +test('supports truncating the output length', () => { const {container} = render('
Hello World!
') expect(prettyDOM(container, 5)).toMatch(/\.\.\./) }) -test('it supports receiving the document element', () => { +test('supports receiving the document element', () => { expect(prettyDOM(document)).toMatchInlineSnapshot(` " diff --git a/src/__tests__/role.js b/src/__tests__/role.js new file mode 100644 index 00000000..77aa9ee1 --- /dev/null +++ b/src/__tests__/role.js @@ -0,0 +1,22 @@ +import {render} from './helpers/test-utils' + +test('logs available roles when it fails', () => { + const {getByRole} = render(`

Hi

`) + expect(() => getByRole('article')).toThrowErrorMatchingInlineSnapshot(` +"Unable to find an element with the role "article" + +Here are the available roles: + + heading: + +

+ + -------------------------------------------------- + +
+

+ Hi +

+
" +`) +}) diff --git a/src/queries/role.js b/src/queries/role.js index 45474211..9ce1fccc 100644 --- a/src/queries/role.js +++ b/src/queries/role.js @@ -1,4 +1,4 @@ -import {getImplicitAriaRoles} from '../role-helpers' +import {getImplicitAriaRoles, prettyRoles} from '../role-helpers' import {buildQueries, fuzzyMatches, makeNormalizer, matches} from './all-utils' function queryAllByRole( @@ -24,8 +24,18 @@ function queryAllByRole( }) } -const getMultipleError = (c, id) => `Found multiple elements by [role=${id}]` -const getMissingError = (c, id) => `Unable to find an element by [role=${id}]` +const getMultipleError = (c, role) => + `Found multiple elements with the role "${role}"` +const getMissingError = (container, role) => + ` +Unable to find an element with the role "${role}" + +Here are the available roles: + + ${prettyRoles(container) + .replace(/\n/g, '\n ') + .replace(/\n\s\s\n/g, '\n\n')} +`.trim() const [ queryByRole, diff --git a/src/role-helpers.js b/src/role-helpers.js index a4fdefed..99e2db8e 100644 --- a/src/role-helpers.js +++ b/src/role-helpers.js @@ -73,10 +73,10 @@ function getRoles(container) { }, {}) } -function logRoles(container) { +function prettyRoles(container) { const roles = getRoles(container) - const rolesStr = Object.entries(roles) + return Object.entries(roles) .map(([role, elements]) => { const delimiterBar = '-'.repeat(50) const elementsString = elements @@ -86,9 +86,11 @@ function logRoles(container) { return `${role}:\n\n${elementsString}\n\n${delimiterBar}` }) .join('\n') +} +function logRoles(container) { // eslint-disable-next-line no-console - console.log(rolesStr) + console.log(prettyRoles(container)) } -export {getRoles, logRoles, getImplicitAriaRoles} +export {getRoles, logRoles, getImplicitAriaRoles, prettyRoles}