Skip to content
This repository has been archived by the owner on Apr 25, 2018. It is now read-only.

Unit test ElementProxy and make related fixes - part one #104

Closed

Conversation

brandonpayton
Copy link
Contributor

@brandonpayton brandonpayton commented May 10, 2016

Hi @garbles,

This is a PR for part one of the ElementProxy unit tests. We still need tests for ElementProxy.fromElement and for set, get, and remove attributes. I'm working on those but am submitting this now with an ElementProxy fix. Insertion, replacement, and removal were broken with regard to text children. The fix is delivered with the unit test commit, which isn't ideal, but was made while writing the tests. Please let me know if you'd like it split into separate commits.

Here's a summary of my changes:

  • Started ElementProxy unit tests
  • Updated ElementProxy.querySelector to return null when no matching element is found
  • Changed ElementProxy#children() to ElementProxy#childNodes and switched the implementation to use the underlying element's childNodes property rather than children because children contains only elements which breaks insert, replace, and remove child operations when working with text nodes.
  • Added _emitMount and _emitUnmount methods to be stubbed by unit test so we can test how they are called by ElementProxy#emitMount and ElementProxy#emitUnmount while relying on the mountable unit tests to test the actual behavior. I don't love this, but it seems like a reasonable compromise.

One question for part two:

  1. What is the intended difference between new ElementProxy(domNode) and ElementProxy.fromElement? I considered removing fromElement but wanted to ask you first.

@jadbox
Copy link
Contributor

jadbox commented May 10, 2016

were broken with regard to text children
Seems suspiciously related to #101 / #103 ... perhaps this is the core issue?

@jadbox
Copy link
Contributor

jadbox commented May 10, 2016

@brandonpayton Can you test this against #103 's test file __test__/regression.test.js?

@brandonpayton
Copy link
Contributor Author

Hi @jadbox, I tried and still saw the failures, which probably makes sense since the ElementProxy issues have to do with the actual DOM, not the virtual nodes that call destroy on their children.

@brandonpayton
Copy link
Contributor Author

@garbles, I just noticed that you're using sinon for stubs elsewhere and will update this PR to use sinon as well.

In addition to the tests, other changes are:
* Updated `ElementProxy.querySelector` to return `null`
when no matching element is found
* Fixed `ElementProxy#children()` to be `ElementProxy#childNodes`
to support text nodes as children
* Added `_emitMount` and `_emitUnmount` methods to be stubbed by unit test
@brandonpayton brandonpayton force-pushed the add-elementproxy-unit-tests branch from 60c89c3 to d6a1111 Compare May 10, 2016 07:31
@brandonpayton
Copy link
Contributor Author

I updated the stubbed ElementProxy tests to use sinon.

I thought I should go ahead and declare remaining ElementProxy tests with it('some pending test case') but failed to consider that it wouldn't match our current interface definition for it. Once I noticed the resulting test failure, I went ahead and updated the interface definition to allow it. Hopefully, you are good with this, but if not, I can remove it.

Thanks!

}

emitUnmount (fn: Function): void {
emitUnmount(this._node, fn)
// Rely on prototype method so it can be stubbed for unit test
this._emitUnmount(this._node, fn)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do this? If fn is falsy, then the mount/unmount event won't fire. I'm not a huge fan of stubbing out another module this way.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the signature should probably be (fn: ?Function): void. That's my fault.

Copy link
Contributor Author

@brandonpayton brandonpayton May 10, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was an attempt at letting the unit tests verify that ElementProxy is interacting with an underlying API so that we don't write the same tests for ElementProxy as we have for mountable. I think it is weak, but it is the best I came up with. What would you do?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to inject emitMount and emitUnmount as part of the argument to the constructor and then test that they're called.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would all uses of ElementProxy be required to provide implementation for emitMount and emitUnmount? If so, that seems overly burdensome given that it is implementation detail that is not likely to be changed except for unit test.

How would references to the injected implementations be maintained? Currently, I imagine it would be the same as this PR but injected via constructor rather than defaults set on the prototype. I may need another clue because my imagination is mostly producing what is here.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea I guess I just don't see the point of calling a function to make sure that another function is called when that function is just a stub. You might as well stub emitMount instead of _emitMount

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it seems a little silly. I was hoping to find a way to declare in the tests that ElementProxy needs to provide emitMount and emitUnmount while not unnecessarily testing what we're already testing for mountable.

Copy link
Contributor Author

@brandonpayton brandonpayton May 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a little more thought, I think it makes sense to test mount events with ElementProxy since ElementProxy is responsible for both adding the listeners and emitting the events. This is in contrast to mountable which is just responsible for emitting. My plan is to back out _emitMount and _emitUnmount and declare those tests to be added in a follow-up PR.

Sound OK?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To shed a little more light on my original thinking, which I'm dropping anyway, the thought for stubbing _emitMount was to declare that ElementProxy relies on something else for emitting and interacts with it according to the call signature. But I don't think it buys anything but a sort of legal satisfaction.

@brandonpayton
Copy link
Contributor Author

I'm closing this and submitting a more limited PR with separate commits for tests and the fixes that satisfy them.

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

Successfully merging this pull request may close these issues.

3 participants