What should the API look like?
mzgoddard opened this issue · comments
Leaving #5 as a place to discuss where and how to announce this package. This Issue is for what the API currently is and how we want it changed to get it to an announcable state.
At this moment, the API is as following
module.exports(vdom) -> SpyWrapper
- shallow(vdom) -> SpyWrapper
- deep(vdom) -> SpyWrapper
- render(vdom) -> SpyWrapper
new FindWrapper(spyWrapper, vdoms, selector)
- at(index) -> FindWrapper
- find(selector) -> FindWrapper
- attr(name) -> Any
- attrs() -> Object
- text() -> String
- contains(vdom) -> Boolean
- simulate(event, ...args)
- output() -> vdom
- filter(selector) -> FindWrapper
new SpyWrapper() extends FindWrapper
- render(vdom, {depth}) -> SpyWrapper
Here is a current possible example
const {render} = require('preact-render-spy');
// ...
const spy = render(<Node />);
spy.find('div').simulate('click');
spy.find('div').text() === 'clicked';
The supported selector
set is currently very small
'div'
or'Node'
: Selects on a native dom element or a preact Component'.class'
or'#id'
: Selects nodes with a class or id attribute set the given class or id'[onClick]'
: Selects nodes with an attribute of this name
The current selector can only be one of these options and cannot be mixed.
I figure this might the minimum we'd add before announcing?
--- current
+++ target
@@ -1,12 +1,18 @@
renderSpy(vdom) -> SpyWrapper
+- shallow(vdom) -> SpyWrapper
+- render(vdom) -> SpyWrapper
new SpyWrapper()
+- shallow(vdom) -> SpyWrapper
- render(vdom) -> SpyWrapper
- find(selector) -> FindWrapper
+- text() -> String
+- contains(vdom) -> Boolean
new FindWrapper(spyWrapper, vdoms, selector)
- at(index) -> FindWrapper
- attr(name) -> Any
+- attrs(name) -> Any[]
- text() -> String
- contains(vdom) -> Boolean
- simulate(event, ...args)
\ No newline at end of file
For selectors we should at least support joined selectors
Such as
.class.class2.class3
Node.anotherClass
And specified attribute values
[name=anchor]
Seems sensible to me.
How does attrs(name)
work? I'd expect attrs()
to return an object, such that
attr('foo') === attrs().foo
Also, what's the difference between renderSpy
and shallow
and render
?
shallow
would "stub" instead of "spy" on child components called for in the resulting JSX after "one level deep"
so shallow(<Node />)
would render that Node, but if it rendered <SubNode />
it wouldn't actually create a SubNode component, just stub it.
whereas render(<Node />)
would go deep?
@mzgoddard any chance you'd be willing to curate the "latest version" in the first comment in the issue as we make changes? so the initial text overviews the issue in case other people show up
Should the FindWrapper
api include find
?
Also, with the wrapper itself, the top level element, without find... can you just call .attr()
etc?
A .children()
api might be useful too.
@mzgoddard any chance you'd be willing to curate the "latest version" in the first comment in the issue as we make changes? so the initial text overviews the issue in case other people show up
Sure!
Should the FindWrapper api include find ?
It's useful but I think its potentially confusing what the output would be. But I'm totally up for having it.
Also, with the wrapper itself, the top level element, without find... can you just call .attr() etc?
You could but you'd just get the attributes on the the node you passed into renderSpy
.
A .children() api might be useful too.
How does that work since preact Components have shadow doms in regards to how this works? You can .find('Node')
but it doesn't have children. It's rendered (shadow) dom may have children. Should it be dereferenced like that?
How does that work since preact Components have shadow doms in regards to how this works? You can .find('Node') but it doesn't have children. It's rendered (shadow) dom may have children. Should it be dereferenced like that?
Literal children of a find... I.E.
const items = [{}, {}, {}];
const context = renderSpy(<List items={items} />);
expect(context.find('ul').children().length).toEqual(items.length);
I would think .children()
of a "functional" node I think would be it's attr('children')
I.E:
const SubNode = ({children}) => <div>{children}</div>;
const Node = () => (
<SubNode>
<span>1</span>
<span>2</span>
</SubNode>
);
expect(renderSpy().shallow(<Node />).find('SubNode').children())
.toEqual(<span>1</span><span>2</span>);
It's the "children" of the node in vdom?
I would think .children() of a "functional" node I think would be it's attr('children')
er wait, it's true for everything isn't it...
Just .children()
would return a FindWrapper
of the .attr('children')
instead of the actual children?
¯\(ツ)/¯ I'm gonna 🍌 myself on that idea and put it aside, it doesn't seem as useful to me anymore...
Yeah. It should be useful. The indirection of components makes it kind of weird. We could make it only children of already selected dom and not component nodes. But that could easily be misunderstood? It just sounds weird.
I'm seeing both of these in the above examples. What's the difference?
renderSpy(<Node />)
renderSpy().shallow(<Node />)
When would one use renderSpy(node)
instead of renderSpy().shallow(node)
or (presumably) renderSpy().render(node)
?
Are shallow
and render
exported so they can be imported like so? Because I don't see why I'd use renderSpy
.
import {shallow, render} from 'preact-render-spy';
It'd be nice to have one clear return from preact-render-spy
and having shallow and render beside each other.
Should the returned objects from shallow
and render
be different @gnarf @cowboy. Should shallow
return an object that can only be shallow rendered from then on? Should render
return an object that can only be deeply rendered from then on?
@mzgoddard I don't see why it would matter... when are you re-rendering the component?
With how preact works I don't see a use in re-rendering. I figured originally it'd be like React which iirc will reuse dom with a top level render call. preact though does a completely fresh render. Which I think I learned after my last post.
But having said that you might use a re-render to test your componentWillUnmount stuff easily. As that lifecycle I'd imagine would still occur. Though if this is the only use, maybe it should be a teardown method intended for that purpose. Hmm.
#9 (comment) is up to date with the API we are likely shipping in version 1. If you'd like to comment further on the API please open a new Issue to discuss the change you are thinking about.