Skip to content

Commit d2c2c91

Browse files
committed
fix query method buttons & cleanup
1 parent a654ea3 commit d2c2c91

File tree

10 files changed

+97
-114
lines changed

10 files changed

+97
-114
lines changed

src/components/Editor.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ const NON_TRIGGER_KEYS = {
153153
};
154154

155155
function formatValue(cm) {
156-
const mode = cm.options.mode.name;
156+
const mode = cm.options.mode;
157157
const value = cm.getValue();
158158
const formatted = beautify.format(mode, value);
159159
cm.setValue(formatted);
@@ -231,11 +231,10 @@ function handleBlur(cm) {
231231
window.addEventListener('message', listener);
232232

233233
// we wait a couple of ms for the SANDBOX_READY event, if that doesn't come
234-
// before given treshold, we assume the user left the editor, and allow it
234+
// before given threshold, we assume the user left the editor, and allow it
235235
// lose focus.
236236
timeout = setTimeout(() => {
237237
window.removeEventListener('message', listener);
238-
formatValue(cm);
239238
}, threshold);
240239
}
241240

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import icon from 'url:~/public/code_thinking.png';
33

4-
function AddHtml() {
4+
function EmptyPane() {
55
return (
66
<div className="flex-auto absolute overflow-hidden h-full w-full flex flex-col justify-center items-center">
77
<div className="h-48 overflow-hidden w-full flex item-center">
@@ -10,9 +10,8 @@ function AddHtml() {
1010
src={icon}
1111
/>
1212
</div>
13-
<p className="opacity-50 ml-24">Try adding some html</p>
1413
</div>
1514
);
1615
}
1716

18-
export default AddHtml;
17+
export default EmptyPane;

src/components/Preview.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useState, useEffect, useRef, useCallback } from 'react';
22
import PreviewHint from './PreviewHint';
3-
import AddHtml from './AddHtml';
3+
import EmptyPane from './EmptyPane';
44
import { getRoles } from '@testing-library/dom';
55

66
function getSandbox(ref) {
@@ -101,7 +101,7 @@ function Preview({ markup, variant, forwardedRef, dispatch }) {
101101

102102
{!markup && (
103103
<div className="absolute w-full h-full top-0 left-0">
104-
<AddHtml />
104+
<EmptyPane />
105105
</div>
106106
)}
107107
</div>

src/components/Result.js

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import ErrorBox from './ErrorBox';
33
import ResultQueries from './ResultQueries';
44
import ResultSuggestion from './ResultSuggestion';
55
import Scrollable from './Scrollable';
6+
import EmptyPane from './EmptyPane';
67

78
function Result({ result, dispatch }) {
89
if (result.error) {
@@ -17,25 +18,12 @@ function Result({ result, dispatch }) {
1718
result.elements.length === 0
1819
) {
1920
return (
20-
<div className="space-y-4 text-sm">
21-
<div className="min-h-8">
22-
<p>
23-
I don&apos;t know what to say. This is a playground for{' '}
24-
<a
25-
href="https://testing-library.com/docs/dom-testing-library/example-intro"
26-
rel="noopener noreferrer"
27-
target="_blank"
28-
className="font-bold"
29-
>
30-
React Testing Library
31-
</a>
32-
.<br /> Please insert some html and queries to be adviced on which
33-
should be used.
34-
</p>
35-
</div>
21+
<div className="flex flex-col relative w-full h-full top-0 left-0">
22+
<EmptyPane />
3623
</div>
3724
);
3825
}
26+
3927
const { data, suggestion, queries } = result.elements[0];
4028
return (
4129
<div className="flex flex-col w-full h-full overflow-hidden">
@@ -55,6 +43,7 @@ function Result({ result, dispatch }) {
5543
suggestion={suggestion}
5644
activeMethod={result.expression?.method}
5745
dispatch={dispatch}
46+
queries={queries}
5847
/>
5948
</Scrollable>
6049
</div>

src/components/Result.test.js

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,16 @@ import cases from 'jest-in-case';
44
import Result from './Result';
55

66
cases(
7-
'should show "I don\'t know" if elements is not an array or if is empty',
7+
'should show image if elements is not an array or if is empty',
88
(opts) => {
9-
render(
10-
<Result
11-
result={{ error: '', expression: {}, elements: opts.elements }}
12-
/>,
13-
);
14-
expect(screen.getByText(/i don't know what to say/i)).toBeInTheDocument();
9+
const result = { error: '', expression: {}, elements: opts.elements };
10+
render(<Result result={result} />);
11+
12+
expect(screen.getByRole('img')).toBeInTheDocument();
1513
},
1614
[
17-
{
18-
name: 'undefined',
19-
elements: undefined,
20-
},
21-
{
22-
name: 'null',
23-
elements: null,
24-
},
25-
{
26-
name: 'empty array',
27-
elements: [],
28-
},
15+
{ name: 'undefined', elements: undefined },
16+
{ name: 'null', elements: null },
17+
{ name: 'empty array', elements: [] },
2918
],
3019
);

src/components/ResultQueries.js

Lines changed: 34 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import { getFieldName } from '../lib';
3-
import { queries } from '../constants';
3+
import { messages as queryGroups } from '../constants';
44

55
function Section({ children }) {
66
return <div className="space-y-3">{children}</div>;
@@ -42,58 +42,43 @@ const Field = React.memo(function Field({
4242
);
4343
});
4444

45+
function QueryGroup({ group, queries, heading, activeMethod, dispatch, data }) {
46+
return (
47+
<Section key={group.type}>
48+
<Heading>{heading}</Heading>
49+
{group.queries.map((queryMethod) => (
50+
<Field
51+
key={queryMethod}
52+
data={data}
53+
method={queryMethod}
54+
query={queries[queryMethod]}
55+
dispatch={dispatch}
56+
active={queryMethod === activeMethod}
57+
/>
58+
))}
59+
</Section>
60+
);
61+
}
4562
// for inputs, the role will only work if there is also a type attribute
46-
function ResultQueries({ data, possibleQueries, dispatch, activeMethod }) {
63+
function ResultQueries(props) {
4764
return (
4865
<div className="grid grid-cols-2 gap-4 pt-4">
49-
<Section>
50-
<Heading>1. Queries Accessible to Everyone</Heading>
51-
{queries
52-
.filter((query) => query.type === 'ACCESSIBLE')
53-
.map((query) => (
54-
<Field
55-
key={query.method}
56-
data={data}
57-
method={query.method}
58-
query={possibleQueries?.[query.method]}
59-
dispatch={dispatch}
60-
active={query.method === activeMethod}
61-
/>
62-
))}
63-
</Section>
64-
66+
<QueryGroup
67+
heading={`1. ${queryGroups[0].heading}`}
68+
group={queryGroups[0]}
69+
{...props}
70+
/>
6571
<div className="space-y-8">
66-
<Section>
67-
<Heading>2. Semantic Queries</Heading>
68-
{queries
69-
.filter((query) => query.type === 'SEMANTIC')
70-
.map((query) => (
71-
<Field
72-
key={query.method}
73-
data={data}
74-
method={query.method}
75-
query={possibleQueries?.[query.method]}
76-
dispatch={dispatch}
77-
active={query.method === activeMethod}
78-
/>
79-
))}
80-
</Section>
81-
82-
<Section>
83-
<Heading>3. TestId</Heading>
84-
{queries
85-
.filter((query) => query.type === 'TEST')
86-
.map((query) => (
87-
<Field
88-
key={query.method}
89-
data={data}
90-
method={query.method}
91-
query={possibleQueries?.[query.method]}
92-
dispatch={dispatch}
93-
active={query.method === activeMethod}
94-
/>
95-
))}
96-
</Section>
72+
<QueryGroup
73+
heading={`2. ${queryGroups[1].heading}`}
74+
group={queryGroups[1]}
75+
{...props}
76+
/>
77+
<QueryGroup
78+
heading={`3. ${queryGroups[2].heading}`}
79+
group={queryGroups[2]}
80+
{...props}
81+
/>
9782
</div>
9883
</div>
9984
);

src/constants.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,26 +40,37 @@ export const queries = [
4040

4141
{ method: 'getByTestId', level: 2, type: 'TEST' },
4242

43-
{ method: 'querySelector', level: 3, type: 'GENERIC' },
43+
{ method: 'querySelector', level: 3, type: 'MANUAL' },
4444
];
4545

46+
function getQueryMethods(type) {
47+
return queries.filter((x) => x.type === type).map((x) => x.method);
48+
}
4649
// some quotes from https://testing-library.com/docs/guide-which-query
4750
export const messages = [
4851
{
4952
heading: 'Queries Accessible to Everyone',
5053
description: `Queries that reflect the experience of visual/mouse users as well as those that use assistive technology. These should be your top preference.`,
54+
type: 'ACCESSIBLE',
55+
queries: getQueryMethods('ACCESSIBLE'),
5156
},
5257
{
5358
heading: 'Semantic Queries',
5459
description: `HTML5 and ARIA compliant selectors. Note that the user experience of interacting with these attributes varies greatly across browsers and assistive technology.`,
60+
type: 'SEMANTIC',
61+
queries: getQueryMethods('SEMANTIC'),
5562
},
5663
{
5764
heading: 'Test IDs',
5865
description: `The user cannot see (or hear) these, so this is only recommended for cases where you can't match by role or text or it doesn't make sense (e.g. the text is dynamic).`,
66+
type: 'TEST',
67+
queries: getQueryMethods('TEST'),
5968
},
6069
{
6170
heading: 'Manual Queries',
6271
description: `On top of the queries provided by the testing library, you can use the regular querySelector DOM API to query elements. Note that using this as an escape hatch to query by class or id is a bad practice because users can't see or identify these attributes. Use a testid if you have to.`,
72+
type: 'MANUAL',
73+
queries: getQueryMethods('MANUAL'),
6374
},
6475
];
6576

src/hooks/usePlayground.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ function reducer(state, action) {
6868
}
6969
}
7070

71+
function init(initialState) {
72+
return {
73+
...initialState,
74+
result: parser.parse(initialState),
75+
};
76+
}
77+
7178
function usePlayground(props) {
7279
let { markup, query, onChange, instanceId, rootNode } = props || {};
7380

@@ -76,13 +83,16 @@ function usePlayground(props) {
7683
query = defaultValues.query;
7784
}
7885

79-
const result = parser.parse({ rootNode, markup, query, cacheId: instanceId });
80-
const [state, dispatch] = useReducer(withLogging(reducer), {
81-
rootNode,
82-
markup,
83-
query,
84-
result,
85-
});
86+
const [state, dispatch] = useReducer(
87+
withLogging(reducer),
88+
{
89+
rootNode,
90+
markup,
91+
query,
92+
cacheId: instanceId,
93+
},
94+
init,
95+
);
8696

8797
useEffect(() => {
8898
if (typeof onChange === 'function') {

src/lib/queryAdvise.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export function getQueryAdvise({ rootNode, element }) {
112112

113113
export function getAllPossibileQueries(element) {
114114
const possibleQueries = queries
115-
.filter((query) => query.type !== 'GENERIC')
115+
.filter((query) => query.type !== 'MANUAL')
116116
.map((query) => {
117117
const method = getFieldName(query.method);
118118
return getSuggestedQuery(element, 'get', method);

src/sandbox.js

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import Scrollable from './components/Scrollable';
55
import setupHighlighter from '../devtools/src/content-script/highlighter';
66
import cssPath from './lib/cssPath';
77
import { getQueryAdvise } from './lib';
8-
import debounce from 'lodash.debounce';
98
import parser from './parser';
109

1110
const state = {
@@ -30,6 +29,7 @@ function runQuery(rootNode, query) {
3029
const result = parser.parse({ rootNode, query });
3130
state.queriedNodes = result.elements.map((elem) => elem.target);
3231
state.highlighter.highlight({ nodes: state.queriedNodes });
32+
return result;
3333
}
3434

3535
function setInnerHTML(node, html) {
@@ -113,14 +113,18 @@ function onSelectNode(node, { origin }) {
113113
postMessage(action);
114114
}
115115

116-
function updateSandbox(rootNode, markup, query) {
116+
function updateMarkup(rootNode, markup, query) {
117117
postMessage({ type: 'SANDBOX_BUSY' });
118118
setInnerHTML(rootNode, markup);
119119
runQuery(rootNode, query);
120120
postMessage({ type: 'SANDBOX_READY' });
121121
}
122122

123-
const updateSandboxDebounced = debounce(updateSandbox, 250);
123+
function updateQuery(rootNode, query) {
124+
postMessage({ type: 'SANDBOX_BUSY' });
125+
runQuery(rootNode, query);
126+
postMessage({ type: 'SANDBOX_READY' });
127+
}
124128

125129
function onMessage({ source, data }) {
126130
if (source !== top || data.source !== 'testing-playground') {
@@ -131,24 +135,21 @@ function onMessage({ source, data }) {
131135
case 'POPULATE_SANDBOX': {
132136
state.query = data.query;
133137
state.markup = data.markup;
134-
break;
135-
}
136-
137-
case 'SET_QUERY': {
138-
state.query = data.query;
138+
updateMarkup(state.rootNode, state.markup, state.query);
139139
break;
140140
}
141141

142142
case 'SET_MARKUP': {
143143
state.markup = data.markup;
144+
updateMarkup(state.rootNode, state.markup, state.query);
144145
break;
145146
}
146-
}
147147

148-
if (data.immediate) {
149-
updateSandbox(state.rootNode, state.markup, state.query);
150-
} else {
151-
updateSandboxDebounced(state.rootNode, state.markup, state.query);
148+
case 'SET_QUERY': {
149+
state.query = data.query;
150+
updateQuery(state.rootNode, state.query);
151+
break;
152+
}
152153
}
153154
}
154155

0 commit comments

Comments
 (0)