enzymejs / enzyme

JavaScript Testing utilities for React
https://enzymejs.github.io/enzyme/
MIT License
19.95k stars 2.01k forks source link

Enzyme cannot find ant design (antd) <Select> class names #2214

Open JESii opened 5 years ago

JESii commented 5 years ago

Thanks for reporting an issue to us! We're glad you are using and invested in Enzyme. Before submitting, please read over our commonly reported issues to prevent duplicates!

All common issues

Notoriously common issues

If you haven't found any duplicated issues, please report it with your environment!

Issue

When creating a Select element with ant design (antd Select), I am unable to find a class that is generated by the Select for the dropdown element.

App Code

image

image

Test Codeimage

Current behavior

find('.bw-select-selection-selected-value') fails to find the desired div

The test fails with: image

Expected behavior

It should find that element, as this Chrome DevTools screenshot shows that the class has been properly rendered. image

Failure analysis

The code that Enzyme generates for the mount() has the class name bw-select-selection-selected-value replaced with ant-select-selection-selected-value as can be seen from the wrapper.debug() output below.

Your environment

API

Version

library version
enzyme 3.9.0
react 16.8.4
react-dom 16.8.4
react-test-renderer not used
adapter (below)

Adapter

wrapper.debug() output

    <AddAssetModal onCancel={[Function: onCancel]} onAddNewAsset={[Function: onAddNewAsset]} uploadFile={[Function: uploadFile]} salesOrderId={111111} mediaRoles={{...}} action="createAsset">
      <Styled(Modal) title={{...}} onOk={[Function: handleUpload]} visible={true} onCancel={[Function: onCancel]} footer={{...}} width={520} transitionName="zoom" maskTransitionName="fade" confirmLoading={false} okType="primary">
        <Modal title={{...}} onOk={[Function: handleUpload]} visible={true} onCancel={[Function: onCancel]} footer={{...}} width={520} transitionName="zoom" maskTransitionName="fade" confirmLoading={false} okType="primary" className="css-19l11x4">
          <DialogWrap title={{...}} onOk={[Function: handleUpload]} onCancel={[Function: onCancel]} width={520} transitionName="zoom" maskTransitionName="fade" confirmLoading={false} okType="primary" className="css-19l11x4" getContainer={[undefined]} prefixCls="ant-modal" wrapClassName="" footer={{...}} visible={true} mousePosition={[undefined]} onClose={[Function]} closeIcon={{...}} forceRender={false}>
            <Portal getContainer={[Function]}>
              <Portal containerInfo={{...}}>
                <Dialog title={{...}} onOk={[Function: handleUpload]} onCancel={[Function: onCancel]} width={520} transitionName="zoom" maskTransitionName="fade" confirmLoading={false} okType="primary" className="css-19l11x4" getContainer={[undefined]} prefixCls="ant-modal" wrapClassName="" footer={{...}} visible={true} mousePosition={[undefined]} onClose={[Function]} closeIcon={{...}} forceRender={false} mask={true} keyboard={true} closable={true} maskClosable={true} destroyOnClose={false}>
                  <div>
                    <Animate showProp="visible" transitionAppear={true} component="" transitionName="fade" animation={{...}} componentProps={{...}} transitionEnter={true} transitionLeave={true} onEnd={[Function: noop]} onEnter={[Function: noop]} onLeave={[Function: noop]} onAppear={[Function: noop]}>
                      <AnimateChild animation={{...}} transitionName="fade" transitionEnter={true} transitionAppear={true} transitionLeave={true}>
                        <LazyRenderBox style={{...}} className="ant-modal-mask" hiddenClassName="ant-modal-mask-hidden" visible={true}>
                          <div style={{...}} className="ant-modal-mask" />
                        </LazyRenderBox>
                      </AnimateChild>
                    </Animate>
                    <div tabIndex={-1} onKeyDown={[Function]} className="ant-modal-wrap " onClick={[Function]} onMouseUp={[Function]} role="dialog" aria-labelledby="rcDialogTitle12" style={{...}}>
                      <Animate showProp="visible" onLeave={[Function]} transitionName="zoom" component="" transitionAppear={true} animation={{...}} componentProps={{...}} transitionEnter={true} transitionLeave={true} onEnd={[Function: noop]} onEnter={[Function: noop]} onAppear={[Function: noop]}>
                        <AnimateChild animation={{...}} transitionName="zoom" transitionEnter={true} transitionAppear={true} transitionLeave={true}>
                          <LazyRenderBox role="document" style={{...}} className="ant-modal css-19l11x4" visible={true} onMouseDown={[Function]}>
                            <div role="document" style={{...}} className="ant-modal css-19l11x4" onMouseDown={[Function]}>
                              <div tabIndex={0} style={{...}} aria-hidden="true" />
                              <div className="ant-modal-content">
                                <button type="button" onClick={[Function]} aria-label="Close" className="ant-modal-close">
                                  <span className="ant-modal-close-x">
                                    <Icon className="ant-modal-close-icon" type="close">
                                      <LocaleReceiver componentName="Icon">
                                        <i aria-label="icon: close" tabIndex={[undefined]} onClick={[undefined]} className="anticon anticon-close ant-modal-close-icon">
                                          <IconReact className="" type="close-o" primaryColor={[undefined]} style={[undefined]}>
                                            <svg viewBox="64 64 896 896" focusable="false" className="" onClick={[undefined]} style={[undefined]} data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true">
                                              <path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z" />
                                            </svg>
                                          </IconReact>
                                        </i>
                                      </LocaleReceiver>
                                    </Icon>
                                  </span>
                                </button>
                                <div className="ant-modal-header">
                                  <div className="ant-modal-title" id="rcDialogTitle12">
                                    <div>
                                      <Icon type="up-circle">
                                        <LocaleReceiver componentName="Icon">
                                          <i aria-label="icon: up-circle" tabIndex={[undefined]} onClick={[undefined]} className="anticon anticon-up-circle">
                                            <IconReact className="" type="up-circle-o" primaryColor={[undefined]} style={[undefined]}>
                                              <svg viewBox="64 64 896 896" focusable="false" className="" onClick={[undefined]} style={[undefined]} data-icon="up-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true">
                                                <path d="M518.5 360.3a7.95 7.95 0 0 0-12.9 0l-178 246c-3.8 5.3 0 12.7 6.5 12.7H381c10.2 0 19.9-4.9 25.9-13.2L512 460.4l105.2 145.4c6 8.3 15.6 13.2 25.9 13.2H690c6.5 0 10.3-7.4 6.5-12.7l-178-246z" />
                                                <path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" />
                                              </svg>
                                            </IconReact>
                                          </i>
                                        </LocaleReceiver>
                                      </Icon>
                                       Add Asset
                                    </div>
                                  </div>
                                </div>
                                <div className="ant-modal-body" style={[undefined]}>
                                  <div>
                                    <Row gutter={0}>
                                      <div className="ant-row" style={[undefined]}>
                                        <Col span={8}>
                                          <div style={[undefined]} className="ant-col ant-col-8">
                                            <MediaRoleSelect id="media-role-select" defaultValue="Select Asset Type" onChange={[Function: bound dispatchAction]}>
                                              <Styled(div)>
                                                <div className="css-1geelec">
                                                  <Select id="media-role-select" defaultValue="Select Asset Type" onChange={[Function: bound dispatchAction]} getPopupContainer={[Function: getPopupContainer]} showSearch={false} transitionName="slide-up" choiceTransitionName="zoom">
                                                    <Select inputIcon={{...}} removeIcon={{...}} clearIcon={{...}} menuItemSelectedIcon={{...}} showArrow={[undefined]} id="media-role-select" defaultValue="Select Asset Type" onChange={[Function: bound dispatchAction]} showSearch={false} transitionName="slide-up" choiceTransitionName="zoom" multiple={false} tags={false} combobox={false} prefixCls="ant-select" className="" optionLabelProp="children" notFoundContent={{...}} getPopupContainer={[Function: getPopupContainer]} defaultOpen={false} labelInValue={false} defaultActiveFirstOption={true} allowClear={false} placeholder="" onFocus={[Function: noop]} onBlur={[Function: noop]} onSelect={[Function: noop]} onSearch={[Function: noop]} onDeselect={[Function: noop]} onInputKeyDown={[Function: noop]} dropdownMatchSelectWidth={true} dropdownStyle={{...}} dropdownMenuStyle={{...}} optionFilterProp="value" backfill={false} showAction={{...}} tokenSeparators={{...}} autoClearSearchValue={true} tabIndex={0} dropdownRender={[Function: dropdownRender]}>
                                                      <SelectTrigger onPopupFocus={[Function]} onMouseEnter={[undefined]} onMouseLeave={[undefined]} dropdownAlign={[undefined]} dropdownClassName={[undefined]} dropdownMatchSelectWidth={true} defaultActiveFirstOption={true} dropdownMenuStyle={{...}} transitionName="slide-up" animation={[undefined]} prefixCls="ant-select" dropdownStyle={{...}} combobox={false} showSearch={false} options={{...}} empty={false} multiple={false} disabled={[undefined]} visible={false} inputValue="" value={{...}} backfillValue="" firstActiveValue={[undefined]} onDropdownVisibleChange={[Function]} getPopupContainer={[Function: getPopupContainer]} onMenuSelect={[Function]} onMenuDeselect={[Function]} onPopupScroll={[undefined]} showAction={{...}} menuItemSelectedIcon={{...}} dropdownRender={[Function: dropdownRender]} ariaId="test-uuid">
                                                        <Trigger onMouseEnter={[undefined]} onMouseLeave={[undefined]} dropdownAlign={[undefined]} dropdownClassName={[undefined]} dropdownMatchSelectWidth={true} defaultActiveFirstOption={true} dropdownMenuStyle={{...}} transitionName="slide-up" animation={[undefined]} prefixCls="ant-select-dropdown" dropdownStyle={{...}} combobox={false} showSearch={false} options={{...}} multiple={false} disabled={[undefined]} visible={false} inputValue="" value={{...}} backfillValue="" firstActiveValue={[undefined]} onDropdownVisibleChange={[Function]} getPopupContainer={[Function: getPopupContainer]} onMenuSelect={[Function]} onMenuDeselect={[Function]} onPopupScroll={[undefined]} showAction={{...}} menuItemSelectedIcon={{...}} dropdownRender={[Function: dropdownRender]} ariaId="test-uuid" hideAction={{...}} popupPlacement="bottomLeft" builtinPlacements={{...}} popupTransitionName="slide-up" onPopupVisibleChange={[Function]} popup={{...}} popupAlign={{...}} popupVisible={false} popupClassName="ant-select-dropdown--single" popupStyle={{...}} getPopupClassNameFromAlign={[Function: returnEmptyString]} getDocument={[Function: returnDocument]} afterPopupVisibleChange={[Function: noop]} onPopupAlign={[Function: noop]} mouseEnterDelay={0} mouseLeaveDelay={0.1} focusDelay={0} blurDelay={0.15} destroyPopupOnHide={false} defaultPopupVisible={false} mask={false} maskClosable={true} action={{...}}>
                                                          <div id="media-role-select" style={[undefined]} onBlur={[Function]} onFocus={[Function]} className="ant-select ant-select-enabled" onMouseDown={[Function]} onMouseUp={[Function]} onMouseOut={[Function]} onContextMenu={[undefined]} onClick={[Function]} onTouchStart={[Function]} onMouseEnter={[undefined]} onMouseLeave={[undefined]}>
                                                            <div className="ant-select-selection\n            ant-select-selection--single" role="combobox" aria-autocomplete="list" aria-haspopup="true" aria-controls="test-uuid" aria-expanded={false} onKeyDown={[Function]} tabIndex={0}>
                                                              <div className="ant-select-selection__rendered">
                                                                <div className="ant-select-selection-selected-value" title="Select Asset Type" style={{...}}>
                                                                  Select Asset Type
                                                                </div>
                                                              </div>
                                                              <span className="ant-select-arrow" style={{...}} unselectable="on" onClick={[Function]}>
                                                                <Icon type="down" className="ant-select-arrow-icon">
                                                                  <LocaleReceiver componentName="Icon">
                                                                    <i aria-label="icon: down" tabIndex={[undefined]} onClick={[undefined]} className="anticon anticon-down ant-select-arrow-icon">
                                                                      <IconReact className="" type="down-o" primaryColor={[undefined]} style={[undefined]}>
                                                                        <svg viewBox="64 64 896 896" focusable="false" className="" onClick={[undefined]} style={[undefined]} data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true">
                                                                          <path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z" />
                                                                        </svg>
                                                                      </IconReact>
                                                                    </i>
                                                                  </LocaleReceiver>
                                                                </Icon>
                                                              </span>
                                                            </div>
                                                          </div>
                                                        </Trigger>
                                                      </SelectTrigger>
                                                    </Select>
                                                  </Select>
                                                </div>
                                              </Styled(div)>
                                            </MediaRoleSelect>
                                          </div>
                                        </Col>
                                        <Col span={16}>
                                          <div style={[undefined]} className="ant-col ant-col-16">
                                            <Styled(span) id="add-asset-error-message">
                                              <span id="add-asset-error-message" className="css-kkep04" />
                                            </Styled(span)>
                                          </div>
                                        </Col>
                                      </div>
                                    </Row>
                                  </div>
                                  <FileDropComponent id="add-asset-file-drop" beforeUpload={[Function: beforeUpload]} showUploadList={{...}} onChange={[Function: onChange]} fileList={{...}}>
                                    <Styled(Dragger) id="add-asset-file-drop" beforeUpload={[Function: beforeUpload]} showUploadList={{...}} onChange={[Function: onChange]} fileList={{...}}>
                                      <Dragger id="add-asset-file-drop" beforeUpload={[Function: beforeUpload]} showUploadList={{...}} onChange={[Function: onChange]} fileList={{...}} className="css-1gzikq2">
                                        <Upload id="add-asset-file-drop" beforeUpload={[Function: beforeUpload]} showUploadList={{...}} onChange={[Function: onChange]} fileList={{...}} className="css-1gzikq2" type="drag" style={{...}} multiple={false} action="" data={{...}} accept="" listType="text" disabled={false} supportServerRender={true}>
                                          <span className="css-1gzikq2">
                                            <div className="ant-upload ant-upload-drag" onDrop={[Function]} onDragOver={[Function]} onDragLeave={[Function]}>
                                              <Upload onStart={[Function]} onError={[Function]} onProgress={[Function]} onSuccess={[Function]} id="add-asset-file-drop" beforeUpload={[Function]} showUploadList={{...}} onChange={[Function: onChange]} fileList={{...}} type="drag" style={{...}} multiple={false} action="" data={{...}} accept="" listType="text" disabled={false} supportServerRender={true} prefixCls="ant-upload" className="ant-upload-btn" component="span" headers={{...}} name="file" multipart={false} onReady={[Function: empty]} customRequest={{...}} withCredentials={false} openFileDialogOnClick={true}>
                                                <AjaxUploader onStart={[Function]} onError={[Function]} onProgress={[Function]} onSuccess={[Function]} id="add-asset-file-drop" beforeUpload={[Function]} showUploadList={{...}} onChange={[Function: onChange]} fileList={{...}} type="drag" style={{...}} multiple={false} action="" data={{...}} accept="" listType="text" disabled={false} supportServerRender={true} prefixCls="ant-upload" className="ant-upload-btn" component="span" headers={{...}} name="file" multipart={false} onReady={[Function: empty]} customRequest={{...}} withCredentials={false} openFileDialogOnClick={true}>
                                                  <span onClick={[Function]} onKeyDown={[Function]} onDrop={[Function]} onDragOver={[Function]} tabIndex="0" className="ant-upload ant-upload-btn" role="button" style={{...}}>
                                                    <input id="add-asset-file-drop" type="file" style={{...}} accept="" directory={{...}} webkitdirectory={{...}} multiple={false} onChange={[Function]} />
                                                    <div className="ant-upload-drag-container">
                                                      <BwIcon type="addPlus">
                                                        <AddIcon>
                                                          <Styled(Icon) type="plus">
                                                            <Icon type="plus" className="css-tqe9q6">
                                                              <LocaleReceiver componentName="Icon">
                                                                <i aria-label="icon: plus" tabIndex={[undefined]} onClick={[undefined]} className="anticon anticon-plus css-tqe9q6">
                                                                  <IconReact className="" type="plus-o" primaryColor={[undefined]} style={[undefined]}>
                                                                    <svg viewBox="64 64 896 896" focusable="false" className="" onClick={[undefined]} style={[undefined]} data-icon="plus" width="1em" height="1em" fill="currentColor" aria-hidden="true">
                                                                      <path d="M482 152h60q8 0 8 8v704q0 8-8 8h-60q-8 0-8-8V160q0-8 8-8z" />
                                                                      <path d="M176 474h672q8 0 8 8v60q0 8-8 8H176q-8 0-8-8v-60q0-8 8-8z" />
                                                                    </svg>
                                                                  </IconReact>
                                                                </i>
                                                              </LocaleReceiver>
                                                            </Icon>
                                                          </Styled(Icon)>
                                                        </AddIcon>
                                                      </BwIcon>
                                                      <Styled(span)>
                                                        <span className="css-3yvibu">
                                                          Add File
                                                        </span>
                                                      </Styled(span)>
                                                      <Styled(span)>
                                                        <span className="css-1whf262">
                                                          Or drop file here
                                                        </span>
                                                      </Styled(span)>
                                                    </div>
                                                  </span>
                                                </AjaxUploader>
                                              </Upload>
                                            </div>
                                            <LocaleReceiver componentName="Upload" defaultLocale={{...}}>
                                              <UploadList listType="text" items={{...}} previewFile={[Function: previewImage]} onPreview={[undefined]} onRemove={[Function]} showRemoveIcon={false} showPreviewIcon={true} locale={{...}} progressAttr={{...}}>
                                                <Animate transitionName="ant-upload-animate" component="div" className="ant-upload-list ant-upload-list-text" animation={{...}} componentProps={{...}} transitionEnter={true} transitionLeave={true} transitionAppear={false} onEnd={[Function: noop]} onEnter={[Function: noop]} onLeave={[Function: noop]} onAppear={[Function: noop]}>
                                                  <div className="ant-upload-list ant-upload-list-text" style={[undefined]} />
                                                </Animate>
                                              </UploadList>
                                            </LocaleReceiver>
                                          </span>
                                        </Upload>
                                      </Dragger>
                                    </Styled(Dragger)>
                                  </FileDropComponent>
                                  <Progress id="add-asset-progress-bar" percent={-1} type="line" showInfo={true} trailColor="#f3f3f3" size="default" gapDegree={0} strokeLinecap="round">
                                    <div id="add-asset-progress-bar" className="ant-progress ant-progress-line ant-progress-status-normal ant-progress-show-info ant-progress-default">
                                      <Line id="add-asset-progress-bar" percent={-1} type="line" showInfo={true} trailColor="#f3f3f3" size="default" gapDegree={0} strokeLinecap="round" prefixCls="ant-progress">
                                        <div>
                                          <div className="ant-progress-outer">
                                            <div className="ant-progress-inner">
                                              <div className="ant-progress-bg" style={{...}} />
                                            </div>
                                          </div>
                                          <span className="ant-progress-text" title="0%">
                                            0%
                                          </span>
                                        </div>
                                      </Line>
                                    </div>
                                  </Progress>
                                </div>
                                <div className="ant-modal-footer">
                                  <Button onClick={[Function: onCancel]} loading={false} ghost={false} block={false} htmlType="button">
                                    <Wave>
                                      <button onClick={[Function]} type="button" className="ant-btn">
                                        <span>
                                          Cancel
                                        </span>
                                      </button>
                                    </Wave>
                                  </Button>
                                  <Button type="primary" id="ok-button" loading={false} disabled={true} onClick={[Function: handleUpload]} ghost={false} block={false} htmlType="button">
                                    <Wave>
                                      <button id="ok-button" disabled={true} onClick={[Function]} type="button" className="ant-btn ant-btn-primary">
                                        <span>
                                          OK
                                        </span>
                                      </button>
                                    </Wave>
                                  </Button>
                                </div>
                              </div>
                              <div tabIndex={0} style={{...}} aria-hidden="true" />
                            </div>
                          </LazyRenderBox>
                        </AnimateChild>
                      </Animate>
                    </div>
                  </div>
                </Dialog>
              </Portal>
            </Portal>
          </DialogWrap>
        </Modal>
      </Styled(Modal)>
    </AddAssetModal>
lucksp commented 4 years ago

I believe the Select is using something like a Portal to render the elements because the options themselves are outside the root of the main app...

ljharb commented 4 years ago

enzyme doesn't generate any code - components themselves do. This just seems like how ant design works - ie, it doesn't actually produce the class names you typed in the actual DOM.