From cfd7ac587eb97a438662ee06747a690b78be4bb1 Mon Sep 17 00:00:00 2001 From: C-Hess Date: Fri, 10 Apr 2020 10:19:41 -0500 Subject: [PATCH] fix: Pass through data and aria attributes (#238) * Add spread operator to pass through props * Use dataOrAttributeProps function instead of omit Credit to DylanVann for dataOrAriaAttributeProps function from https://github.com/react-component/notification/pull/54/files * Add tests for "role" attribute passthrough Co-authored-by: Cameron Hessler --- src/AjaxUploader.jsx | 14 ++++++++++ tests/uploader.spec.js | 59 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/src/AjaxUploader.jsx b/src/AjaxUploader.jsx index 248e3e1..638c90f 100644 --- a/src/AjaxUploader.jsx +++ b/src/AjaxUploader.jsx @@ -6,6 +6,18 @@ import getUid from './uid'; import attrAccept from './attr-accept'; import traverseFileTree from './traverseFileTree'; +const dataOrAriaAttributeProps = (props) => { + return Object.keys(props).reduce( + (acc, key) => { + if (key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-' || key === 'role') { + acc[key] = props[key]; + } + return acc; + }, + {}, + ); +}; + class AjaxUploader extends Component { state = { uid: getUid() } @@ -199,6 +211,7 @@ class AjaxUploader extends Component { const { component: Tag, prefixCls, className, disabled, id, style, multiple, accept, children, directory, openFileDialogOnClick, + ...otherProps, } = this.props; const cls = classNames({ [prefixCls]: true, @@ -220,6 +233,7 @@ class AjaxUploader extends Component { style={style} > { describe('uploader', () => { let requests; let xhr; + let errorMock; beforeEach(() => { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = req => requests.push(req); + + const originalConsoleError = global.console.error; + errorMock = jest.spyOn(global.console, 'error'); + errorMock.mockImplementation((message, ...otherParams) => { + originalConsoleError(message, ...otherParams); + throw new Error(format(message, ...otherParams)); + }); }); afterEach(() => { xhr.restore(); + errorMock.mockRestore(); }); describe('ajax uploader', () => { @@ -116,6 +126,55 @@ describe('uploader', () => { }); }); + it('should pass through data attributes', done => { + ReactDOM.render( + ( + + ), + node, + function init() { + expect(TestUtils.findRenderedDOMComponentWithTag(this, 'input') + .getAttribute('data-testid')) + .to.be('data-testid'); + expect(TestUtils.findRenderedDOMComponentWithTag(this, 'input') + .getAttribute('data-my-custom-attr')) + .to.be('custom data attribute'); + done(); + } + ); + }); + + it('should pass through aria attributes', done => { + ReactDOM.render(, node, function init() { + expect(TestUtils.findRenderedDOMComponentWithTag(this, 'input') + .getAttribute('aria-label')) + .to.be('Upload a file'); + done(); + }); + }); + + it('should pass through role attributes', done => { + ReactDOM.render(, node, function init() { + expect(TestUtils.findRenderedDOMComponentWithTag(this, 'input') + .getAttribute('role')) + .to.be('button'); + done(); + }); + }); + + it('should not pass through unknown props', done => { + ReactDOM.render(, + node, + () => { + // Fails when React reports unrecognized prop is added to DOM in console.error + done(); + } + ); + }); + it('create works', () => { expect(TestUtils.scryRenderedDOMComponentsWithTag(uploader, 'span').length).to.be(1); });