Skip to content

Commit ecc2b7f

Browse files
committed
refactor: simplify navigation
1 parent abe8d71 commit ecc2b7f

File tree

4 files changed

+15
-143
lines changed

4 files changed

+15
-143
lines changed

src/helpers/__tests__/component-tree.test.tsx

Lines changed: 2 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
import React from 'react';
2-
import { Text, TextInput, View } from 'react-native';
2+
import { View } from 'react-native';
33
import { render, screen } from '../..';
4-
import {
5-
getHostChildren,
6-
getHostSelves,
7-
getHostSiblings,
8-
getUnsafeRootElement,
9-
} from '../component-tree';
4+
import { getHostSiblings, getUnsafeRootElement } from '../component-tree';
105

116
function MultipleHostChildren() {
127
return (
@@ -18,98 +13,6 @@ function MultipleHostChildren() {
1813
);
1914
}
2015

21-
describe('getHostChildren()', () => {
22-
it('returns host children for host component', () => {
23-
render(
24-
<View testID="grandparent">
25-
<View testID="parent">
26-
<View testID="subject" />
27-
<Text testID="sibling">Hello</Text>
28-
</View>
29-
</View>,
30-
);
31-
32-
const hostSubject = screen.getByTestId('subject');
33-
expect(getHostChildren(hostSubject)).toEqual([]);
34-
35-
const hostSibling = screen.getByTestId('sibling');
36-
expect(getHostChildren(hostSibling)).toEqual([]);
37-
38-
const hostParent = screen.getByTestId('parent');
39-
expect(getHostChildren(hostParent)).toEqual([hostSubject, hostSibling]);
40-
41-
const hostGrandparent = screen.getByTestId('grandparent');
42-
expect(getHostChildren(hostGrandparent)).toEqual([hostParent]);
43-
});
44-
45-
it('returns host children for composite component', () => {
46-
render(
47-
<View testID="parent">
48-
<MultipleHostChildren />
49-
<View testID="subject" />
50-
<View testID="sibling" />
51-
</View>,
52-
);
53-
54-
expect(getHostChildren(screen.getByTestId('parent'))).toEqual([
55-
screen.getByTestId('child1'),
56-
screen.getByTestId('child2'),
57-
screen.getByTestId('child3'),
58-
screen.getByTestId('subject'),
59-
screen.getByTestId('sibling'),
60-
]);
61-
});
62-
});
63-
64-
describe('getHostSelves()', () => {
65-
it('returns passed element for host components', () => {
66-
render(
67-
<View testID="grandparent">
68-
<View testID="parent">
69-
<View testID="subject" />
70-
<View testID="sibling" />
71-
</View>
72-
</View>,
73-
);
74-
75-
const hostSubject = screen.getByTestId('subject');
76-
expect(getHostSelves(hostSubject)).toEqual([hostSubject]);
77-
78-
const hostSibling = screen.getByTestId('sibling');
79-
expect(getHostSelves(hostSibling)).toEqual([hostSibling]);
80-
81-
const hostParent = screen.getByTestId('parent');
82-
expect(getHostSelves(hostParent)).toEqual([hostParent]);
83-
84-
const hostGrandparent = screen.getByTestId('grandparent');
85-
expect(getHostSelves(hostGrandparent)).toEqual([hostGrandparent]);
86-
});
87-
88-
test('returns single host element for React Native composite components', () => {
89-
render(
90-
<View testID="parent">
91-
<Text testID="text">Text</Text>
92-
<TextInput
93-
testID="textInput"
94-
defaultValue="TextInputValue"
95-
placeholder="TextInputPlaceholder"
96-
/>
97-
</View>,
98-
);
99-
100-
const compositeText = screen.getByText('Text');
101-
const hostText = screen.getByTestId('text');
102-
expect(getHostSelves(compositeText)).toEqual([hostText]);
103-
104-
const compositeTextInputByValue = screen.getByDisplayValue('TextInputValue');
105-
const compositeTextInputByPlaceholder = screen.getByPlaceholderText('TextInputPlaceholder');
106-
107-
const hostTextInput = screen.getByTestId('textInput');
108-
expect(getHostSelves(compositeTextInputByValue)).toEqual([hostTextInput]);
109-
expect(getHostSelves(compositeTextInputByPlaceholder)).toEqual([hostTextInput]);
110-
});
111-
});
112-
11316
describe('getHostSiblings()', () => {
11417
it('returns host siblings for host component', () => {
11518
render(

src/helpers/component-tree.ts

Lines changed: 5 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,51 +8,17 @@ export function isHostElement(element?: HostElement | null): element is HostElem
88
return typeof element?.type === 'string' && element.type !== 'CONTAINER';
99
}
1010

11-
/**
12-
* Returns host children for given element.
13-
* @param element The element start traversing from.
14-
*/
15-
export function getHostChildren(element: HostElement | null): HostElement[] {
16-
if (element == null) {
17-
return [];
18-
}
19-
20-
const hostChildren: HostElement[] = [];
21-
22-
element.children.forEach((child) => {
23-
if (typeof child !== 'object') {
24-
return;
25-
}
26-
27-
if (isHostElement(child)) {
28-
hostChildren.push(child);
29-
} else {
30-
hostChildren.push(...getHostChildren(child));
31-
}
32-
});
33-
34-
return hostChildren;
35-
}
36-
37-
/**
38-
* Return the array of host elements that represent the passed element.
39-
*
40-
* @param element The element start traversing from.
41-
* @returns If the passed element is a host element, it will return an array containing only that element,
42-
* if the passed element is a composite element, it will return an array containing its host children (zero, one or many).
43-
*/
44-
export function getHostSelves(element: HostElement | null): HostElement[] {
45-
return isHostElement(element) ? [element] : getHostChildren(element);
46-
}
47-
4811
/**
4912
* Returns host siblings for given element.
5013
* @param element The element start traversing from.
5114
*/
5215
export function getHostSiblings(element: HostElement | null): HostElement[] {
5316
const hostParent = element?.parent ?? null;
54-
const hostSelves = getHostSelves(element);
55-
return getHostChildren(hostParent).filter((sibling) => !hostSelves.includes(sibling));
17+
return (
18+
hostParent?.children.filter(
19+
(sibling): sibling is HostElement => typeof sibling === 'object' && sibling !== element,
20+
) ?? []
21+
);
5622
}
5723

5824
/**

src/matchers/to-be-empty-element.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import { matcherHint, RECEIVED_COLOR } from 'jest-matcher-utils';
2-
import { getHostChildren } from '../helpers/component-tree';
32
import { HostElement } from '../renderer/host-element';
43
import { checkHostElement, formatElementArray } from './utils';
54

65
export function toBeEmptyElement(this: jest.MatcherContext, element: HostElement) {
76
checkHostElement(element, toBeEmptyElement, this);
87

9-
const hostChildren = getHostChildren(element);
8+
const hostChildren = element.children;
109

1110
return {
1211
pass: hostChildren.length === 0,

src/matchers/utils.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import prettyFormat, { plugins } from 'pretty-format';
1010
import redent from 'redent';
1111
import { isHostElement } from '../helpers/component-tree';
1212
import { defaultMapProps } from '../helpers/format-default';
13-
import { HostElement } from '../renderer/host-element';
13+
import { HostElement, HostNode } from '../renderer/host-element';
1414

1515
class HostElementTypeError extends Error {
1616
constructor(received: unknown, matcherFn: jest.CustomMatcher, context: jest.MatcherContext) {
@@ -60,11 +60,15 @@ export function checkHostElement(
6060
*
6161
* @param element Element to format.
6262
*/
63-
export function formatElement(element: HostElement | null) {
63+
export function formatElement(element: HostNode | null) {
6464
if (element == null) {
6565
return ' null';
6666
}
6767

68+
if (typeof element === 'string') {
69+
return element;
70+
}
71+
6872
const { children, ...props } = element.props;
6973
const childrenToDisplay = typeof children === 'string' ? [children] : undefined;
7074

@@ -89,7 +93,7 @@ export function formatElement(element: HostElement | null) {
8993
);
9094
}
9195

92-
export function formatElementArray(elements: HostElement[]) {
96+
export function formatElementArray(elements: HostNode[]) {
9397
if (elements.length === 0) {
9498
return ' (no elements)';
9599
}

0 commit comments

Comments
 (0)