Added some component filtering tests
Brian Vaughn committed
May 1, 2019 at 13:31 UTC
540207901d4af2ed894b76b6693f9d9c84f2711a
9 files changed
+318
-9
babel.config.js
+1
@@ -29,6 +29,7 @@ module.exports = api => {
29
plugins: [
30
['@babel/plugin-transform-flow-strip-types'],
31
['@babel/plugin-proposal-class-properties', { loose: false }],
32
+ ['@babel/plugin-transform-react-jsx-source'],
33
],
34
presets: [
35
['@babel/preset-env', { targets }],
package.json
+1
@@ -70,6 +70,7 @@
70
"@babel/core": "^7.1.6",
71
"@babel/plugin-proposal-class-properties": "^7.1.0",
72
"@babel/plugin-transform-flow-strip-types": "^7.1.6",
73
+ "@babel/plugin-transform-react-jsx-source": "^7.2.0",
74
"@babel/preset-env": "^7.1.6",
75
"@babel/preset-flow": "^7.0.0",
76
"@babel/preset-react": "^7.0.0",
src/__tests__/__snapshots__/storeComponentFilters-test.js.snap
new
+98
@@ -0,0 +1,98 @@
1
+// Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+exports[`Store component filters should filter by display name: 1: mount 1`] = `
4
+[root]
5
+ ▾ <Foo>
6
+ <Text>
7
+ ▾ <Bar>
8
+ <Text>
9
+ ▾ <Baz>
10
+ <Text>
11
+`;
12
+
13
+exports[`Store component filters should filter by display name: 2: filter "Foo" 1`] = `
14
+[root]
15
+ <Text>
16
+ ▾ <Bar>
17
+ <Text>
18
+ ▾ <Baz>
19
+ <Text>
20
+`;
21
+
22
+exports[`Store component filters should filter by display name: 3: filter "Ba" 1`] = `
23
+[root]
24
+ ▾ <Foo>
25
+ <Text>
26
+ <Text>
27
+ <Text>
28
+`;
29
+
30
+exports[`Store component filters should filter by display name: 4: filter "B.z" 1`] = `
31
+[root]
32
+ ▾ <Foo>
33
+ <Text>
34
+ ▾ <Bar>
35
+ <Text>
36
+ <Text>
37
+`;
38
+
39
+exports[`Store component filters should filter by path: 1: mount 1`] = `
40
+[root]
41
+ ▾ <Component>
42
+ <div>
43
+`;
44
+
45
+exports[`Store component filters should filter by path: 2: hide all components declared within this test filed 1`] = `[root]`;
46
+
47
+exports[`Store component filters should filter by path: 3: hide components in a made up fake path 1`] = `
48
+[root]
49
+ ▾ <Component>
50
+ <div>
51
+`;
52
+
53
+exports[`Store component filters should ignore invalid ElementTypeRoot filter: 1: mount 1`] = `
54
+[root]
55
+ ▾ <Root>
56
+ <div>
57
+`;
58
+
59
+exports[`Store component filters should ignore invalid ElementTypeRoot filter: 2: add invalid filter 1`] = `
60
+[root]
61
+ ▾ <Root>
62
+ <div>
63
+`;
64
+
65
+exports[`Store component filters should support filtering by element type: 1: mount 1`] = `
66
+[root]
67
+ ▾ <Root>
68
+ ▾ <div>
69
+ ▾ <Component>
70
+ <div>
71
+`;
72
+
73
+exports[`Store component filters should support filtering by element type: 2: hide host components 1`] = `
74
+[root]
75
+ ▾ <Root>
76
+ <Component>
77
+`;
78
+
79
+exports[`Store component filters should support filtering by element type: 3: hide class components 1`] = `
80
+[root]
81
+ ▾ <div>
82
+ ▾ <Component>
83
+ <div>
84
+`;
85
+
86
+exports[`Store component filters should support filtering by element type: 4: hide class and function components 1`] = `
87
+[root]
88
+ ▾ <div>
89
+ <div>
90
+`;
91
+
92
+exports[`Store component filters should support filtering by element type: 5: disable all filters 1`] = `
93
+[root]
94
+ ▾ <Root>
95
+ ▾ <div>
96
+ ▾ <Component>
97
+ <div>
98
+`;
src/__tests__/storeComponentFilters-test.js
new
+191
@@ -0,0 +1,191 @@
1
+// @flow
2
+
3
+describe('Store component filters', () => {
4
+ let React;
5
+ let ReactDOM;
6
+ let TestUtils;
7
+ let Types;
8
+ let store;
9
+
10
+ const createElementTypeFilter = (elementType, isEnabled = true) => ({
11
+ type: Types.ComponentFilterElementType,
12
+ isEnabled,
13
+ value: elementType,
14
+ });
15
+
16
+ const createDisplayNameFilter = (source, isEnabled = true) => {
17
+ let isValid = true;
18
+ try {
19
+ new RegExp(source);
20
+ } catch (error) {
21
+ isValid = false;
22
+ }
23
+ return {
24
+ type: Types.ComponentFilterDisplayName,
25
+ isEnabled,
26
+ isValid,
27
+ value: source,
28
+ };
29
+ };
30
+
31
+ const createLocationFilter = (source, isEnabled = true) => {
32
+ let isValid = true;
33
+ try {
34
+ new RegExp(source);
35
+ } catch (error) {
36
+ isValid = false;
37
+ }
38
+ return {
39
+ type: Types.ComponentFilterLocation,
40
+ isEnabled,
41
+ isValid,
42
+ value: source,
43
+ };
44
+ };
45
+
46
+ const act = (callback: Function) => {
47
+ TestUtils.act(() => {
48
+ callback();
49
+ });
50
+ jest.runAllTimers(); // Flush Bridge operations
51
+ };
52
+
53
+ beforeEach(() => {
54
+ store = global.store;
55
+ store.collapseNodesByDefault = false;
56
+ store.componentFilters = [];
57
+
58
+ React = require('react');
59
+ ReactDOM = require('react-dom');
60
+ TestUtils = require('react-dom/test-utils');
61
+ Types = require('src/types');
62
+ });
63
+
64
+ it('should support filtering by element type', () => {
65
+ class Root extends React.Component<{| children: React$Node |}> {
66
+ render() {
67
+ return <div>{this.props.children}</div>;
68
+ }
69
+ }
70
+ const Component = () => <div>Hi</div>;
71
+
72
+ act(() =>
73
+ ReactDOM.render(
74
+ <Root>
75
+ <Component />
76
+ </Root>,
77
+ document.createElement('div')
78
+ )
79
+ );
80
+ expect(store).toMatchSnapshot('1: mount');
81
+
82
+ act(
83
+ () =>
84
+ (store.componentFilters = [
85
+ createElementTypeFilter(Types.ElementTypeHostComponent),
86
+ ])
87
+ );
88
+
89
+ expect(store).toMatchSnapshot('2: hide host components');
90
+
91
+ act(
92
+ () =>
93
+ (store.componentFilters = [
94
+ createElementTypeFilter(Types.ElementTypeClass),
95
+ ])
96
+ );
97
+
98
+ expect(store).toMatchSnapshot('3: hide class components');
99
+
100
+ act(
101
+ () =>
102
+ (store.componentFilters = [
103
+ createElementTypeFilter(Types.ElementTypeClass),
104
+ createElementTypeFilter(Types.ElementTypeFunction),
105
+ ])
106
+ );
107
+
108
+ expect(store).toMatchSnapshot('4: hide class and function components');
109
+
110
+ act(
111
+ () =>
112
+ (store.componentFilters = [
113
+ createElementTypeFilter(Types.ElementTypeClass, false),
114
+ createElementTypeFilter(Types.ElementTypeFunction, false),
115
+ ])
116
+ );
117
+
118
+ expect(store).toMatchSnapshot('5: disable all filters');
119
+ });
120
+
121
+ it('should ignore invalid ElementTypeRoot filter', () => {
122
+ const Root = () => <div>Hi</div>;
123
+
124
+ act(() => ReactDOM.render(<Root />, document.createElement('div')));
125
+ expect(store).toMatchSnapshot('1: mount');
126
+
127
+ act(
128
+ () =>
129
+ (store.componentFilters = [
130
+ createElementTypeFilter(Types.ElementTypeRoot),
131
+ ])
132
+ );
133
+
134
+ expect(store).toMatchSnapshot('2: add invalid filter');
135
+ });
136
+
137
+ it('should filter by display name', () => {
138
+ const Text = ({ label }) => label;
139
+ const Foo = () => <Text label="foo" />;
140
+ const Bar = () => <Text label="bar" />;
141
+ const Baz = () => <Text label="baz" />;
142
+
143
+ act(() =>
144
+ ReactDOM.render(
145
+ <React.Fragment>
146
+ <Foo />
147
+ <Bar />
148
+ <Baz />
149
+ </React.Fragment>,
150
+ document.createElement('div')
151
+ )
152
+ );
153
+ expect(store).toMatchSnapshot('1: mount');
154
+
155
+ act(() => (store.componentFilters = [createDisplayNameFilter('Foo')]));
156
+ expect(store).toMatchSnapshot('2: filter "Foo"');
157
+
158
+ act(() => (store.componentFilters = [createDisplayNameFilter('Ba')]));
159
+ expect(store).toMatchSnapshot('3: filter "Ba"');
160
+
161
+ act(() => (store.componentFilters = [createDisplayNameFilter('B.z')]));
162
+ expect(store).toMatchSnapshot('4: filter "B.z"');
163
+ });
164
+
165
+ it('should filter by path', () => {
166
+ const Component = () => <div>Hi</div>;
167
+
168
+ act(() => ReactDOM.render(<Component />, document.createElement('div')));
169
+ expect(store).toMatchSnapshot('1: mount');
170
+
171
+ act(
172
+ () =>
173
+ (store.componentFilters = [
174
+ createLocationFilter(__filename.replace(__dirname, '')),
175
+ ])
176
+ );
177
+
178
+ expect(store).toMatchSnapshot(
179
+ '2: hide all components declared within this test filed'
180
+ );
181
+
182
+ act(
183
+ () =>
184
+ (store.componentFilters = [
185
+ createLocationFilter('this:is:a:made:up:path'),
186
+ ])
187
+ );
188
+
189
+ expect(store).toMatchSnapshot('3: hide components in a made up fake path');
190
+ });
191
+});
src/backend/renderer.js
+6
-3
@@ -4,7 +4,7 @@ import { gte } from 'semver';
4
import {
5
ComponentFilterDisplayName,
6
ComponentFilterElementType,
7
- ComponentFilterPath,
7
+ ComponentFilterLocation,
8
ElementTypeClass,
9
ElementTypeContext,
10
ElementTypeEventComponent,
@@ -290,7 +290,7 @@ export function attach(
290
case ComponentFilterElementType:
291
hideElementsWithTypes.add(componentFilter.value);
292
break;
293
- case ComponentFilterPath:
293
+ case ComponentFilterLocation:
294
if (componentFilter.isValid && componentFilter.value !== '') {
295
hideElementsWithPaths.add(new RegExp(componentFilter.value, 'i'));
296
}
@@ -354,6 +354,9 @@ export function attach(
354
case HostText:
355
case Fragment:
356
return true;
357
+ case HostRoot:
358
+ // It is never valid to filter the root element.
359
+ return false;
360
default:
361
const typeSymbol = getTypeSymbol(type);
362
@@ -383,7 +386,7 @@ export function attach(
386
}
387
}
388
386
- if (_debugSource !== null && hideElementsWithPaths.size > 0) {
389
+ if (_debugSource != null && hideElementsWithPaths.size > 0) {
390
const { fileName } = _debugSource;
391
for (let pathRegExp of hideElementsWithPaths) {
392
if (pathRegExp.test(fileName)) {
src/devtools/views/Components/ComponentFiltersModal.css
+1
-1
@@ -66,7 +66,7 @@
66
}
67
68
.Input {
69
- border: none;
69
+ border: 1px solid var(--color-border);
70
border-radius: 0.125rem;
71
padding: 0.125rem;
72
}
src/devtools/views/Components/ComponentFiltersModal.js
+4
-4
@@ -17,7 +17,7 @@ import Store from 'src/devtools/store';
17
import {
18
ComponentFilterElementType,
19
ComponentFilterDisplayName,
20
- ComponentFilterPath,
20
+ ComponentFilterLocation,
21
ElementTypeClass,
22
ElementTypeContext,
23
ElementTypeEventTarget,
@@ -164,9 +164,9 @@ function ComponentFiltersModal({ store, setIsModalShowing }: Props) {
164
)
165
}
166
>
167
- <option value={ComponentFilterElementType}>type</option>
167
+ <option value={ComponentFilterLocation}>location</option>
168
<option value={ComponentFilterDisplayName}>name</option>
169
- <option value={ComponentFilterPath}>path</option>
169
+ <option value={ComponentFilterElementType}>type</option>
170
</select>
171
</td>
172
<td className={styles.TableCell}>
@@ -295,7 +295,7 @@ function useComponentFilters() {
295
}: ElementTypeComponentFilter);
296
} else if (
297
type === ComponentFilterDisplayName ||
298
- type === ComponentFilterPath
298
+ type === ComponentFilterLocation
299
) {
300
// $FlowFixMe TODO (filters)
301
cloned[index] = ({
src/types.js
+1
-1
@@ -40,7 +40,7 @@ export type ElementType = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
40
// If new filter types are added, use new numbers rather than re-ordering existing ones.
41
export const ComponentFilterElementType = 1;
42
export const ComponentFilterDisplayName = 2;
43
-export const ComponentFilterPath = 3;
43
+export const ComponentFilterLocation = 3;
44
45
export type FilterType = 1 | 2 | 3;
46
yarn.lock
+15
@@ -383,6 +383,13 @@
383
dependencies:
384
"@babel/helper-plugin-utils" "^7.0.0"
385
386
+"@babel/plugin-syntax-jsx@^7.2.0":
387
+ version "7.2.0"
388
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz#0b85a3b4bc7cdf4cc4b8bf236335b907ca22e7c7"
389
+ integrity sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==
390
+ dependencies:
391
+ "@babel/helper-plugin-utils" "^7.0.0"
392
+
393
"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.2.0":
394
version "7.2.0"
395
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e"
@@ -605,6 +612,14 @@
612
"@babel/helper-plugin-utils" "^7.0.0"
613
"@babel/plugin-syntax-jsx" "^7.0.0"
614
615
+"@babel/plugin-transform-react-jsx-source@^7.2.0":
616
+ version "7.2.0"
617
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.2.0.tgz#20c8c60f0140f5dd3cd63418d452801cf3f7180f"
618
+ integrity sha512-A32OkKTp4i5U6aE88GwwcuV4HAprUgHcTq0sSafLxjr6AW0QahrCRCjxogkbbcdtpbXkuTOlgpjophCxb6sh5g==
619
+ dependencies:
620
+ "@babel/helper-plugin-utils" "^7.0.0"
621
+ "@babel/plugin-syntax-jsx" "^7.2.0"
622
+
623
"@babel/plugin-transform-react-jsx@^7.0.0":
624
version "7.1.6"
625
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.1.6.tgz#e6188e7d2a2dcd2796d45a87f8b0a8c906f57d1a"