Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shallow render components #12

Open
k-ode opened this issue Jun 1, 2016 · 4 comments
Open

Shallow render components #12

k-ode opened this issue Jun 1, 2016 · 4 comments

Comments

@k-ode
Copy link

k-ode commented Jun 1, 2016

One of the nice things about testing React components with Enzyme is that you can test your components as shallow. In this case, only the top level component gets rendered and all child components are ignored. This makes a lot of sense for unit testing, since you want to test your components as small, independent parts.

It would be nice if you could just call renderShallowComponent(...), but I'm guessing that would also be really involved. I can't say I have any idea how this would be implemented, maybe override the component binding somehow?

A simpler method would be an option to ignore certain components. So if you have a TodoList you could do:

renderComponent({
    viewModel: TodoList,
    template: todoListTemplate,
    ignoreComponents: ['Todo']
})

These sub components would be registered as empty components. This is what I currently do in a before-call, but it would be tidier to have the functionality built in.

Thoughts?

@caseyWebb
Copy link
Contributor

This is pretty much the default if you don't register the child components. If you want to block those registrations you can do it with a component loader.

ko.components.loaders.splice(1, 0, {
  getConfig(name, callback) {
    const isSUT = name === '_SUT' // this is the name the tester uses to register components
    const emptyComponentConfig = { template: document.createElement('div') }
    callback(isSUT ? null : emptyComponentConfig)
  }
})

We insert at the 2nd position in the array to preserve $.fn.getComponentParams which
uses a component loader itself to intercept the params. See here. Now you can go one step farther and assert your child components were passed the correct params.

const parent = {
  viewModel() { this.childText = 'foo' },
  template: '<child params="text: childText"></child>'
}

const $parent = renderComponent(parent)
const $child = $('child', $el)

$child.getComponentParams() === { text: 'foo' }

@caseyWebb
Copy link
Contributor

This could — and should — be incorporated into the api somehow.

@k-ode
Copy link
Author

k-ode commented Jun 2, 2016

Thanks for the clarification! That's very useful information.

However, I forgot to mention that we use the component-binding syntax for a lot for our sub components. And while it is true that custom elements are ignored if they are not registered, the component binding actually complains with Uncaught Error: Unknown component 'todo'.

We have to use the component binding sometimes because - unlike custom elements - it can be used as a virtual node. This is important if you use something like flexbox which doesn't work right with the extra dom elements that a custom element brings. It's also useful if you have to pass a lot arguments to a component, then you can just pass it as a object in the parent view model.

@k-ode
Copy link
Author

k-ode commented Jun 2, 2016

The custom loader you outlined does solve this, I just wanted to clarify our use case.

I had to change the argument to template to an array though.

ko.components.loaders.splice(1, 0, {
    getConfig(name, callback) {
        const isSUT = name === '_SUT'; // this is the name the tester uses to register components
        const emptyComponentConfig = { template: [document.createElement('div')] };
        callback(isSUT ? null : emptyComponentConfig);
    }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants