Skip to content

Commit

Permalink
feat(a11y): custom renderers passed onPress prop now have a11y roles
Browse files Browse the repository at this point in the history
  • Loading branch information
jsamr committed Sep 11, 2021
1 parent dd988fc commit 11723f0
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import {
defaultHTMLElementModels,
HTMLContentModel,
TBlock
} from '@native-html/transient-render-engine';
import { render } from '@testing-library/react-native';
import React from 'react';
import AccessibilityEngine from 'react-native-accessibility-engine';
import RenderHTML from '../RenderHTML';
import { CustomRendererProps } from '../shared-types';

describe('RenderHTML a11y', () => {
describe('regarding anchors', () => {
Expand Down Expand Up @@ -82,4 +88,62 @@ describe('RenderHTML a11y', () => {
expect(() => AccessibilityEngine.check(element)).not.toThrow();
});
});
describe('regarding pressable custom renderers', () => {
it('should add a button role if onPress is defined for custom renderers with a block content model', () => {
const element = (
<RenderHTML
source={{
html: '<button aria-label="Click me!"></button>'
}}
customHTMLElementModels={{
...defaultHTMLElementModels,
button: defaultHTMLElementModels.button.extend({
contentModel: HTMLContentModel.block
})
}}
renderers={{
button: ({
TDefaultRenderer,
...props
}: CustomRendererProps<TBlock>) => (
<TDefaultRenderer onPress={() => {}} {...props} />
)
}}
debug={false}
contentWidth={200}
/>
);
const { getByA11yRole } = render(element);
const buttonProps = getByA11yRole('button').props;
expect(buttonProps.accessibilityRole).toBe('button');
expect(() => AccessibilityEngine.check(element)).not.toThrow();
});
it('should add a button role if onPress is defined for custom renderers with a textual content model', () => {
const element = (
<RenderHTML
source={{
html: '<span><customlink aria-label="Click me!"></customlink></span>'
}}
customHTMLElementModels={{
...defaultHTMLElementModels,
customlink: defaultHTMLElementModels.span
}}
renderers={{
customlink: ({
TDefaultRenderer,
...props
}: CustomRendererProps<any>) => (
<TDefaultRenderer onPress={() => {}} {...props} />
)
}}
debug={false}
contentWidth={200}
/>
);
const { getByA11yRole } = render(element);
const buttonProps = getByA11yRole('link').props;
expect(buttonProps.accessibilityRole).toBe('link');
expect(() => AccessibilityEngine.check(element)).not.toThrow();
});
});
});
6 changes: 5 additions & 1 deletion packages/render-html/src/helpers/getNativePropsForTNode.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { TBlock, TPhrasing, TText } from '@native-html/transient-render-engine';
import { TextProps, ViewProps } from 'react-native';
import { TDefaultRendererProps } from '../shared-types';

/**
Expand All @@ -8,10 +9,13 @@ import { TDefaultRendererProps } from '../shared-types';
*/
export default function getNativePropsForTNode(
props: TDefaultRendererProps<TPhrasing | TText | TBlock>
) {
): TextProps | ViewProps {
const { tnode, style, type, nativeProps, onPress } = props;
const switchProp = type === 'block' ? props.viewProps : props.textProps;
return {
...(typeof onPress === 'function'
? ({ accessibilityRole: type === 'block' ? 'button' : 'link' } as const)
: null),
...tnode.getReactNativeProps()?.[type === 'block' ? 'view' : 'text'],
...nativeProps,
...switchProp,
Expand Down

0 comments on commit 11723f0

Please sign in to comment.