mirror of
https://github.com/callstack/react-native-testing-library.git
synced 2026-09-18 23:09:04 +08:00
fix: accessible name calculation (#1910)
This commit is contained in:
committed by
GitHub
parent
7ce8b09123
commit
2c32ce75df
@@ -864,6 +864,37 @@ describe('computeAccessibleName', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('concatenates inline text children without extra spaces', async () => {
|
||||
const name = 'World';
|
||||
|
||||
await render(<Text testID="subject">Hello {name}!</Text>);
|
||||
|
||||
expect(computeAccessibleName(screen.getByTestId('subject'))).toBe('Hello World!');
|
||||
});
|
||||
|
||||
test('concatenates nested inline Text children without extra spaces', async () => {
|
||||
const name = 'World';
|
||||
|
||||
await render(
|
||||
<Text testID="subject">
|
||||
Hello <Text>{name}</Text>!
|
||||
</Text>,
|
||||
);
|
||||
|
||||
expect(computeAccessibleName(screen.getByTestId('subject'))).toBe('Hello World!');
|
||||
});
|
||||
|
||||
test('separates non-text accessible names inside Text from adjacent inline text', async () => {
|
||||
await render(
|
||||
<Text testID="subject">
|
||||
<View aria-label="icon" />
|
||||
<Text>label</Text>
|
||||
</Text>,
|
||||
);
|
||||
|
||||
expect(computeAccessibleName(screen.getByTestId('subject'))).toBe('icon label');
|
||||
});
|
||||
|
||||
test('TextInput placeholder is used only for the element itself', async () => {
|
||||
await render(
|
||||
<>
|
||||
|
||||
@@ -268,6 +268,11 @@ type ComputeAccessibleNameOptions = {
|
||||
root?: boolean;
|
||||
};
|
||||
|
||||
type AccessibleNamePart = {
|
||||
text: string;
|
||||
isInlineText: boolean;
|
||||
};
|
||||
|
||||
export function computeAccessibleName(
|
||||
instance: TestInstance,
|
||||
options?: ComputeAccessibleNameOptions,
|
||||
@@ -281,21 +286,36 @@ export function computeAccessibleName(
|
||||
return instance.props.placeholder;
|
||||
}
|
||||
|
||||
const parts = [];
|
||||
const parts: AccessibleNamePart[] = [];
|
||||
for (const child of instance.children) {
|
||||
if (typeof child === 'string') {
|
||||
if (child) {
|
||||
parts.push(child);
|
||||
parts.push({ text: child, isInlineText: true });
|
||||
}
|
||||
} else {
|
||||
const childLabel = computeAccessibleName(child, { root: false });
|
||||
if (childLabel) {
|
||||
parts.push(childLabel);
|
||||
parts.push({ text: childLabel, isInlineText: isHostText(child) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parts.join(' ');
|
||||
return joinAccessibleNameParts(parts, { inline: isHostText(instance) });
|
||||
}
|
||||
|
||||
function joinAccessibleNameParts(
|
||||
parts: AccessibleNamePart[],
|
||||
options: { inline: boolean },
|
||||
): string {
|
||||
return parts.reduce((accessibleName, part, index) => {
|
||||
if (index === 0) {
|
||||
return part.text;
|
||||
}
|
||||
|
||||
const previousPart = parts[index - 1];
|
||||
const separator = options.inline && previousPart.isInlineText && part.isInlineText ? '' : ' ';
|
||||
return `${accessibleName}${separator}${part.text}`;
|
||||
}, '');
|
||||
}
|
||||
|
||||
type RoleSupportMap = Partial<Record<Role | AccessibilityRole, true>>;
|
||||
|
||||
@@ -207,6 +207,34 @@ describe('supports name option', () => {
|
||||
expect(screen.getByRole('header', { name: 'About' }).props.testID).toBe('target-header');
|
||||
});
|
||||
|
||||
test('returns an element when inline text children form the name', async () => {
|
||||
const name = 'World';
|
||||
|
||||
await render(
|
||||
<Text accessibilityRole="header" testID="target-header">
|
||||
Hello {name}!
|
||||
</Text>,
|
||||
);
|
||||
|
||||
expect(screen.getByRole('header', { name: 'Hello World!' })).toBe(
|
||||
screen.getByTestId('target-header'),
|
||||
);
|
||||
});
|
||||
|
||||
test('returns an element when nested inline Text children form the name', async () => {
|
||||
const name = 'World';
|
||||
|
||||
await render(
|
||||
<Text accessibilityRole="header" testID="target-header">
|
||||
Hello <Text>{name}</Text>!
|
||||
</Text>,
|
||||
);
|
||||
|
||||
expect(screen.getByRole('header', { name: 'Hello World!' })).toBe(
|
||||
screen.getByTestId('target-header'),
|
||||
);
|
||||
});
|
||||
|
||||
test('returns an element with nested Text as children', async () => {
|
||||
await render(
|
||||
<Text accessibilityRole="header" testID="parent">
|
||||
|
||||
Reference in New Issue
Block a user