It appears that find, can't find html elements by class like HTMLAnchorElement
test("can find anchors", ()=> {
const wrapper = mount(<div><a href="#"></a></div>);
expect(wrapper.find('a').length).toBe(1); // passes
expect(wrapper.childAt(0).instance()).toBeInstanceOf(HTMLAnchorElement); //passes
expect(wrapper.find(HTMLAnchorElement).length).toBe(1); //fails
});
test("can find spans", ()=> {
const wrapper = mount(<div><span>Test</span></div>);
expect(wrapper.find('span').length).toBe(1); //passes
expect(wrapper.childAt(0).instance()).toBeInstanceOf(HTMLSpanElement); //passes
expect(wrapper.find(HTMLSpanElement).length).toBe(1); //fails
});
"next": "^7.0.2",
"react": "^16.4.2",
"react-dom": "^16.4.2",
"enzyme": "^3.5.0",
"enzyme-adapter-react-16": "^1.3.0",
"jest": "^23.5.0",
| library | version
| ------------------- | -------
| enzyme | ^3.5.0
| react | ^16.4.2
| react-dom |^16.4.2
| react-test-renderer | ???
| adapter (below) | ^1.3.0
That is very much not something we ever expected anyone would do. Can you elaborate on your use case? (Considering you can get and find by the tag name, or by the .type())
No, special use case, it was just the first way I tried, at first I thought my code was broken. If this isn't something you want to fix, that's okay the other method works fine, and I can still get access to the HTMLAnchorElement and HTMLSpanElements.
What do you mean by .type()
On the enzyme wrapper, you can call .type() and it will give you either the component function or the html tag name, which can be passed into .find().
The reason I thought it was odd, is this passes
test("can find Layout", ()=> {
const wrapper = mount(<div><Layout title="Layout"></Layout></div>);
expect(wrapper.find('Layout').length).toBe(1); // passes
expect(wrapper.childAt(0).instance()).toBeInstanceOf(Layout); //passes
expect(wrapper.find(Layout).length).toBe(1); //passes
});
I just looked at the docs for .type(), and understand I think why it works on custom elements and not html elements.
If it's a native DOM node, it will be a string of the tag name.
I assume the .type method is used internally by the find function, and fixing this would be a breaking change, is that correct?
In general I wouldn't use .instance() for that - instead, expect(wrapper.childAt(0).is(Layout)).toBe(true).
There's nothing to fix - React itself uses a string for HTML tags - it's very rare for anything in the entire JS ecosystem to use DOM constructors directly.
To clarify; nothing to fix in .type() - it definitely seems like a reasonable feature request to be able to find DOM elements by constructor.
I would like to help this out :)
@ljharb Here's my plan on approaching this feature. I'm going to write the test cases for all the HTML element constructor. and each of it will basically be something like
`it('finds area element with HTMLAreaElement', () => {
const Component = mount(
expect(Component.find(HTMLAreaElement).length).toBe(1);
});`
After writing all the test cases. I will then implement the feature within the reduceTreesBySelector function (because find uses that with the selector) and implement some function there (havent fully thought through yet.
However, I have one question. For the time being. How do i import the HTMLElements constructor/class
That seems like a good approach.
In a browser, they鈥檒l be globals - but in node, they鈥檒l be nonexistent. So we鈥檒l need to code for both cases gracefully, using typeof (and using skip in the tests as needed). We鈥檒l want to be sure we have test cases for both mount and shallow.
How would I be able to know if the test is running in a browser or in node?
The test cases that I will be writing in ReactWrapper.spec.js will be run in node right? What should I use to replace the HTMLElement since I do not have access to it? Or am I able to write test cases that run in either a browser or node environment?
And noted, I will be sure to write for both mount and shallow. Should i write for this whole list of HTMLElement though, or only a specific few?
// HTMLAnchorElement// HTMLAreaElement// HTMLAudioElement// HTMLBRElement// HTMLBaseElement// HTMLBaseFontElement// HTMLBodyElement// HTMLButtonElement// HTMLCanvasElement// HTMLContentElement// HTMLDListElement// HTMLDataElement// HTMLDataListElement// HTMLDialogElement// HTMLDivElement// HTMLDocument// HTMLEmbedElement// HTMLFieldSetElement// HTMLFormControlsCollection// HTMLFormElement// HTMLFrameSetElement// HTMLHRElement// HTMLHeadElement// HTMLHeadingElement// HTMLHtmlElement// HTMLIFrameElement// HTMLImageElement// HTMLInputElement// HTMLIsIndexElement// HTMLKeygenElement// HTMLLIElement// HTMLLabelElement// HTMLLegendElement// HTMLLinkElement// HTMLMapElement// HTMLMediaElement // HTMLMetaElement// HTMLMeterElement// HTMLModElement// HTMLOListElement// HTMLObjectElement// HTMLOptGroupElement// HTMLOptionElement// HTMLOptionsCollection// HTMLOutputElement// HTMLParagraphElement// HTMLParamElement// HTMLPictureElement// HTMLPreElement// HTMLProgressElement// HTMLQuoteElement// HTMLScriptElement// HTMLSelectElement// HTMLShadowElement// HTMLSourceElement// HTMLSpanElement// HTMLStyleElement// HTMLTableCaptionElement// HTMLTableCellElement// HTMLTableColElement// HTMLTableDataCellElement// HTMLTableElement// HTMLTableHeaderCellElement// HTMLTableRowElement// HTMLTableSectionElement// HTMLTemplateElement// HTMLTextAreaElement // HTMLTimeElement // HTMLTitleElement // HTMLTrackElement // HTMLUListElement // HTMLUnknownElement // HTMLVideoElement
You can't know; all you can do is check if typeof HTMLAnchorElement === 'undefined' or not, etc.
It would be a good idea to test for everything that we might be able to support.
I might be misunderstanding this and correct me if i'm wrong. But if that's the case, then we couldnt write test cases in ReactWrapper.spec.js like this
expect(Component.find(HTMLAreaElement).length).toBe(1);
});
because the HTMLAreaElement couldnt be defined in the first place?
And if I am wrong, how should I go about writing a test case?
That test will work fine - when the tests are run in an environment that has a DOM available. In node, they鈥檒l be skipped.
Ok, got it. I'm gonna write the test cases for all of them and then make a PR for you to check and provide suggestions. When those are good, I'll work on on the feature then.