diff --git a/devtools/src/devtools/components/MenuBar.js b/devtools/src/devtools/components/MenuBar.js
index 8067cd50..567eac97 100644
--- a/devtools/src/devtools/components/MenuBar.js
+++ b/devtools/src/devtools/components/MenuBar.js
@@ -37,7 +37,7 @@ function MenuBar({ cssPath, suggestion }) {
className="focus:outline-none"
title="Inspect the matching DOM element"
disabled={!cssPath}
- onClick={() => inspectedWindow.inspect(cssPath)}
+ onClick={() => inspectedWindow.inspect(cssPath.toString())}
>
diff --git a/package-lock.json b/package-lock.json
index afd970e9..d166fce5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3270,9 +3270,9 @@
}
},
"@testing-library/dom": {
- "version": "7.12.0",
- "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.12.0.tgz",
- "integrity": "sha512-DaP36Pa7G8cFros2MFQWNQsZSwl1DjG/OYQzFSM6gt1N1bzxsqb1GaxPo6LyTKA622xDC2KqPpqF+PsOlYd00Q==",
+ "version": "7.15.0",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.15.0.tgz",
+ "integrity": "sha512-H+cQksHNYjxTS62S+exT5ZcBZeJXE3NDHUKs6MTopp4cMgd8DHX78IUohyUGqJRD1AthtgnKujrPTxYdWZ/w9w==",
"requires": {
"@babel/runtime": "^7.10.2",
"aria-query": "^4.0.2",
diff --git a/package.json b/package.json
index c48d1f7f..8e0e6072 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,7 @@
"postversion": "git push && git push --tags && git checkout master && git merge develop --ff && git push && git checkout -"
},
"dependencies": {
- "@testing-library/dom": "^7.12.0",
+ "@testing-library/dom": "^7.15.0",
"codemirror": "5.54.0",
"crx-bridge": "^2.1.0",
"deep-diff": "^1.0.2",
diff --git a/src/components/Result.js b/src/components/Result.js
index f771ef83..9cfe0713 100644
--- a/src/components/Result.js
+++ b/src/components/Result.js
@@ -3,7 +3,6 @@ import ErrorBox from './ErrorBox';
import ResultQueries from './ResultQueries';
import ResultSuggestion from './ResultSuggestion';
import Scrollable from './Scrollable';
-import { emptyResult } from '../lib';
function Result({ result, dispatch }) {
if (result.error) {
@@ -37,9 +36,7 @@ function Result({ result, dispatch }) {
);
}
-
- const { data, suggestion } = result.elements?.[0] || emptyResult;
-
+ const { data, suggestion, queries } = result.elements[0];
return (
@@ -55,6 +52,7 @@ function Result({ result, dispatch }) {
{children}
;
}
function Heading({ children }) {
- return
{children} ;
+ return
{children} ;
}
-const Field = React.memo(function Field({ method, data, dispatch, active }) {
+const Field = React.memo(function Field({
+ data,
+ method,
+ query,
+ dispatch,
+ active,
+}) {
const field = getFieldName(method);
const value = data[field];
-
const handleClick = value
? () => {
- const expression = getExpression({ method, data });
- dispatch({ type: 'SET_QUERY', query: expression });
+ dispatch({
+ type: 'SET_QUERY',
+ query: `screen.${query.toString()}`,
+ });
}
: undefined;
@@ -26,7 +34,7 @@ const Field = React.memo(function Field({ method, data, dispatch, active }) {
data-clickable={!!handleClick}
onClick={handleClick}
>
-
{field}
+
{field}
{value || n/a }
@@ -35,68 +43,62 @@ const Field = React.memo(function Field({ method, data, dispatch, active }) {
});
// for inputs, the role will only work if there is also a type attribute
-function ResultQueries({ data, dispatch, activeMethod }) {
+function ResultQueries({ data, possibleQueries, dispatch, activeMethod }) {
return (
1. Queries Accessible to Everyone
-
-
-
-
-
+ {queries
+ .filter((query) => query.type === 'ACCESSIBLE')
+ .map((query) => {
+ return (
+
+ );
+ })}
2. Semantic Queries
-
-
+ {queries
+ .filter((query) => query.type === 'SEMANTIC')
+ .map((query) => {
+ return (
+
+ );
+ })}
3. TestId
-
+ {queries
+ .filter((query) => query.type === 'TEST')
+ .map((query) => {
+ return (
+
+ );
+ })}
diff --git a/src/constants.js b/src/constants.js
index 710afa21..a7801e49 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -25,18 +25,22 @@ screen.getByRole('button')
};
export const queries = [
- { method: 'getByRole', level: 0 },
- { method: 'getByLabelText', level: 0 },
- { method: 'getByPlaceholderText', level: 0 },
- { method: 'getByText', level: 0 },
- { method: 'getByDisplayValue', level: 0 },
+ { method: 'getByRole', level: 0, type: 'ACCESSIBLE' },
+ { method: 'getByLabelText', level: 0, type: 'ACCESSIBLE' },
+ {
+ method: 'getByPlaceholderText',
+ level: 0,
+ type: 'ACCESSIBLE',
+ },
+ { method: 'getByText', level: 0, type: 'ACCESSIBLE' },
+ { method: 'getByDisplayValue', level: 0, type: 'ACCESSIBLE' },
- { method: 'getByAltText', level: 1 },
- { method: 'getByTitle', level: 1 },
+ { method: 'getByAltText', level: 1, type: 'SEMANTIC' },
+ { method: 'getByTitle', level: 1, type: 'SEMANTIC' },
- { method: 'getByTestId', level: 2 },
+ { method: 'getByTestId', level: 2, type: 'TEST' },
- { method: 'querySelector', level: 3 },
+ { method: 'querySelector', level: 3, type: 'GENERIC' },
];
// some quotes from https://testing-library.com/docs/guide-which-query
diff --git a/src/lib/getExpression.js b/src/lib/getExpression.js
deleted file mode 100644
index b04d3ee7..00000000
--- a/src/lib/getExpression.js
+++ /dev/null
@@ -1,41 +0,0 @@
-export function wrapInQuotes(val) {
- if (!val.includes(`'`)) {
- return `'${val}'`;
- }
-
- if (!val.includes('"')) {
- return `"${val}"`;
- }
-
- if (!val.includes('`')) {
- return `\`${val}\``;
- }
-
- return `'${val.replace(/'/g, `\\'`)}'`;
-}
-
-export function getFieldName(method) {
- return method[5].toLowerCase() + method.substr(6);
-}
-
-export function getExpression({ method, data }) {
- const field = getFieldName(method);
-
- if (method === 'getByRole') {
- if (data.role && data.name) {
- const matcher = new RegExp(`${data.name}`.toLowerCase(), 'i');
- return `screen.getByRole('${data.role}', { name: ${matcher} })`;
- } else {
- return `screen.getByRole('${data.role}')`;
- }
- }
-
- if (data[field]) {
- const matcher = new RegExp(`${data[field]}`.toLowerCase(), 'i');
- return `screen.${method}(${matcher})`;
- }
-
- return '';
-}
-
-export default getExpression;
diff --git a/src/lib/getFieldName.js b/src/lib/getFieldName.js
new file mode 100644
index 00000000..c01942ab
--- /dev/null
+++ b/src/lib/getFieldName.js
@@ -0,0 +1,19 @@
+export function wrapInQuotes(val) {
+ if (!val.includes(`'`)) {
+ return `'${val}'`;
+ }
+
+ if (!val.includes('"')) {
+ return `"${val}"`;
+ }
+
+ if (!val.includes('`')) {
+ return `\`${val}\``;
+ }
+
+ return `'${val.replace(/'/g, `\\'`)}'`;
+}
+
+export function getFieldName(method) {
+ return method[5].toLowerCase() + method.substr(6);
+}
diff --git a/src/lib/index.js b/src/lib/index.js
index 9369f952..8801cc40 100644
--- a/src/lib/index.js
+++ b/src/lib/index.js
@@ -1,3 +1,3 @@
export * from './ensureArray';
-export * from './getExpression';
+export * from './getFieldName';
export * from './queryAdvise';
diff --git a/src/lib/queryAdvise.js b/src/lib/queryAdvise.js
index 34bbe091..88e5ea8e 100644
--- a/src/lib/queryAdvise.js
+++ b/src/lib/queryAdvise.js
@@ -2,6 +2,7 @@ import { messages, queries } from '../constants';
import { computeAccessibleName, getRole } from 'dom-accessibility-api';
import { getSuggestedQuery } from '@testing-library/dom';
import cssPath from './cssPath';
+import { getFieldName } from './';
export function getData({ rootNode, element }) {
const type = element.getAttribute('type');
@@ -80,3 +81,19 @@ export function getQueryAdvise({ rootNode, element }) {
suggestion,
};
}
+
+export function getAllPossibileQueries(element) {
+ const possibleQueries = queries
+ .filter((query) => query.type !== 'GENERIC')
+ .map((query) => {
+ const method = getFieldName(query.method);
+ return getSuggestedQuery(element, 'get', method);
+ })
+ .filter((suggestedQuery) => suggestedQuery !== undefined)
+ .reduce((obj, suggestedQuery) => {
+ obj[suggestedQuery.queryMethod] = suggestedQuery;
+ return obj;
+ }, {});
+
+ return possibleQueries;
+}
diff --git a/src/lib/queryAdvise.test.js b/src/lib/queryAdvise.test.js
index 353c8f6c..993832e0 100644
--- a/src/lib/queryAdvise.test.js
+++ b/src/lib/queryAdvise.test.js
@@ -1,4 +1,4 @@
-import { getQueryAdvise } from './queryAdvise';
+import { getQueryAdvise, getAllPossibileQueries } from './queryAdvise';
const emptyObject = `
Object {
@@ -48,3 +48,111 @@ it('should add `screen.` on suggested query returned by getSuggestedQuery', () =
const result = getQueryAdvise({ rootNode, element });
expect(result.suggestion.expression).toStartWith('screen.');
});
+
+it('[getAllPossibileQueries] should return an object with all possibile queries', () => {
+ const rootNode = document.createElement('div');
+ const element = document.createElement('button');
+ rootNode.appendChild(element);
+ let suggestedQueries = getAllPossibileQueries(element);
+
+ expect(suggestedQueries).toMatchInlineSnapshot(`
+ Object {
+ "getByRole": Object {
+ "queryArgs": Array [
+ "button",
+ ],
+ "queryMethod": "getByRole",
+ "queryName": "Role",
+ "toString": [Function],
+ "variant": "get",
+ },
+ }
+ `);
+
+ rootNode.innerHTML = `
+
Username
+
+ `;
+ const input = rootNode.querySelector('input');
+ suggestedQueries = getAllPossibileQueries(input);
+
+ expect(suggestedQueries).toMatchInlineSnapshot(`
+ Object {
+ "getByAltText": Object {
+ "queryArgs": Array [
+ /enter your username/i,
+ ],
+ "queryMethod": "getByAltText",
+ "queryName": "AltText",
+ "toString": [Function],
+ "variant": "get",
+ },
+ "getByDisplayValue": Object {
+ "queryArgs": Array [
+ /john-doe/i,
+ ],
+ "queryMethod": "getByDisplayValue",
+ "queryName": "DisplayValue",
+ "toString": [Function],
+ "variant": "get",
+ },
+ "getByLabelText": Object {
+ "queryArgs": Array [
+ /username/i,
+ ],
+ "queryMethod": "getByLabelText",
+ "queryName": "LabelText",
+ "toString": [Function],
+ "variant": "get",
+ },
+ "getByPlaceholderText": Object {
+ "queryArgs": Array [
+ /how should i call you\\?/i,
+ ],
+ "queryMethod": "getByPlaceholderText",
+ "queryName": "PlaceholderText",
+ "toString": [Function],
+ "variant": "get",
+ },
+ "getByRole": Object {
+ "queryArgs": Array [
+ "textbox",
+ Object {
+ "name": /username/i,
+ },
+ ],
+ "queryMethod": "getByRole",
+ "queryName": "Role",
+ "toString": [Function],
+ "variant": "get",
+ },
+ "getByTestId": Object {
+ "queryArgs": Array [
+ "uname",
+ ],
+ "queryMethod": "getByTestId",
+ "queryName": "TestId",
+ "toString": [Function],
+ "variant": "get",
+ },
+ "getByTitle": Object {
+ "queryArgs": Array [
+ /enter your username/i,
+ ],
+ "queryMethod": "getByTitle",
+ "queryName": "Title",
+ "toString": [Function],
+ "variant": "get",
+ },
+ }
+ `);
+});
diff --git a/src/parser.js b/src/parser.js
index e23d4cef..51b67f04 100644
--- a/src/parser.js
+++ b/src/parser.js
@@ -3,6 +3,7 @@ import { ensureArray, getQueryAdvise } from './lib';
import { queries as supportedQueries } from './constants';
import cssPath from './lib/cssPath';
import deepEqual from './lib/deepEqual';
+import { getAllPossibileQueries } from './lib/queryAdvise';
import {
getQueriesForElement,
@@ -123,6 +124,7 @@ function createEvaluator({ rootNode }) {
data,
target: element,
cssPath: cssPath(element, true),
+ queries: getAllPossibileQueries(element),
};
});